This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| vsscanf for Win32 Submitted by

I don't how many times I've been irritated by the fact that Microsoft chose to implement all the v*printf family of routines, but for some odd reason decided to leave out all the v*scanf routines. It is all the more frustrating that the functionality is actually present inside their crt library (in a function called input, which is not exported). From there your choices are as follows:

> - Write your own vsscanf
> - Rip the source out of crt and graft it into your app.
> - Use a third party implementation (trio is a good one, btw).

All these solutions suck: if you choose to write your own, you'll soon discover how hard it is to write an ANSI conforming scanf, other than hacking together Frankenstein code that is half yours, and half calling the native system sscanf when things gets hard (float conversion springs to mind). If you choose a third party implementation (crt, trio, glibc, ...), there's the usual problems: it's usually much bulkier than you'd like, doesn't compile the way you have your tree setup, comes with hieroglyphic Makefiles, carries crual and unusual licensing agreements, and basically adds a maintenance burden to your already complicated work day. Given all this, and the fact that irritation always ends up breeding code, here's my solution to the problem: since sscanf is available in the system, I've implemented vsscanf by hacking together a fake stack before hoping into sscanf. Advantages:

> - It works
> - It is small
> - It has no strings attached
> - In time, it inherits all maintenance work done by MSFT on scanf

Disadvantages:

> - It adds a tiny overhead (browsing the fmt for % signs)
> - It is not portable (although the technique is)
> - But then again the rest of the universe *does* implement vsscanf, so who cares.

Enjoy,
- mgix PS: This is written with Visual C++ inline assembly. If someone gets around to writing the equivalent in the weird gcc inline assembly linguo, please send it my way. Thanks.

Download Associated File: vsscanf.txt (3,040 bytes)

    /*

    I don't how many time I've been irritated by the fact that Microsoft
    chose to implement all the v*printf family of routines, but for some
    odd reason decided to leave out all the v*scanf routines.

    It is all the more frustrating that the functionality is actually
    present inside their crt library (in a function called input, which is
    not exported).

    >From there your choices are as follows:

    	- Write your own vsscanf
    	- Rip the source out of crt and graft it into your app.
    	- Use a third party implementation (trio is a good one, btw).

    All these solutions suck: if you choose to write your own, you'll soon
    discover how hard it is to write an ANSI conforming scanf, other than
    hacking together Frankenstein code that is half yours, and half calling
    the native system sscanf when things gets hard (float conversion springs
    to mind).

    If you choose a third party implementation (crt, trio, glibc, ...), there's
    the usual problems: it's usually much bulkier than you'd like, doesn't compile
    the way you have your tree setup, comes with hieroglyphic Makefiles, carries crual
    and unusual licensing agreements, and basically adds a maintenance burden to your
    already complicated work day.

    Given all this, and the fact that irritation always ends up breeding code,
    here's my solution to the problem: since sscanf is available in the system,
    I've implemented vsscanf by hacking together a fake stack before hoping into sscanf.

    Advantages:
    	- It works
    	- It is small
    	- It has no strings attached
    	- In time, it inherits all maintenance work done by MSFT on scanf

    Disadvantages:
    	- It adds a tiny overhead (browsing the fmt for % signs)
    	- It is not portable (although the technique is)
    	- But then again the rest of the universe *does* implement
    	  vsscanf, so who cares.

    Enjoy,

    	- mgix

    PS: This is written with Visual C++ inline assembly. If someone gets
    around to writing the equivalent in the weird gcc inline assembly linguo,
    please send it my way. Thanks.

    */

    /*
     * vsscanf for Win32
     *
     * Written 5/2003 by <mgix@mgix.com>
     *
     * This code is in the Public Domain
     *
     */

    #include <stdio.h>
    #include <stdarg.h>
    #include <malloc.h>
    #include <string.h>

    int vsscanf(
        const char  *buffer,
        const char  *format,
        va_list     argPtr
    )
    {
        // Get an upper bound for the # of args
        size_t count = 0;
        const char *p = format;
        while(1)
        {
            char c = *(p++);
            if(c==0) break;
            if(c=='%' && (p[0]!='*' && p[0]!='%')) ++count;
        }

        // Make a local stack
        size_t stackSize = (2+count)*sizeof(void*);
        void **newStack = (void**)alloca(stackSize);

        // Fill local stack the way sscanf likes it
        newStack[0] = (void*)buffer;
        newStack[1] = (void*)format;
        memcpy(newStack+2, argPtr, count*sizeof(void*));

        // Warp into system sscanf with new stack
        int result;
        void *savedESP;
        _asm
        {
            mov     savedESP, esp;
            mov     esp, newStack;
            call    sscanf;
            mov     esp, savedESP;
            mov     result, eax;
        }
        return result;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.