enum values to strings.

Neil Williams linux at codehelp.co.uk
Thu Mar 24 16:32:33 EST 2005


That anti-software patent meeting has had an unexpected side effect. After the 
meeting, I got chatting about GnuCash and my development work on QOF (as you 
do). One of the results was a discussion about how to turn enum values 
(integers) into strings (for text file readability) using #define. 

I experimented with the code that had been jotted down on the back of EU 
software patent EP 0760140 (!) and also found this example:
http://www.flipcode.com/cgi-bin/fcmsg.cgi?thread_show=24481

That doesn't work for me, so I've got a version here that DOES work as 
straight C (I think):

Credit to Jamie Lokier for the original idea and Chad Austin for the flipcode 
example in C++. I'm posting it here in case I've missed something obvious.
;-)

#include <stdio.h>
#define ENUM_BODY(name, value) \
    name = value,
#define AS_STRING_CASE(name, value) \
    case name: return #name;
#define FROM_STRING_CASE(name, value) \
    if (strcmp(str, #name) == 0) {    \
        return name;                  \
    }
#define DEFINE_ENUM(name, list)                 \
    typedef enum {                              \
        list(ENUM_BODY)                         \
    }name;                                      \
    const char* asString(name n) {              \
        switch (n) {                            \
            list(AS_STRING_CASE)                \
            default: return "";                 \
        }                                       \
    }                                           \
    name fromString(const char* str) {          \
        list(FROM_STRING_CASE)                  \
        return 0; /* assert? throw? */     \
    }
#define ENUM_LIST(_)                             \
    _(RED,   0)                                  \
    _(GREEN, 1)                                  \
    _(BLUE,  87)

DEFINE_ENUM(Color, ENUM_LIST)

int main() {
    Color c = GREEN;
    printf("%d\n",c);
    printf("%s\n", asString(c));
    printf("%d\n", fromString("BLUE"));
}

gcc enum.c

Output:

neil at garfield:~/tmp/enum$ ./a.out
1
GREEN
87

 I need this functionality to convert potentially any enum already defined in 
GnuCash into a form that is usable AS an enum by all existing processes and 
which can be converted to a const char* on demand, with only one piece of new 
code, no duplication and as efficiently as possible. Only enums that are used 
as QOF parameters (presently gint32/gint64) would actually take this new 
form. The parameter would then be changed to QOF_TYPE_STRING and a function 
defined. That would get the enum from the existing function (as a wrapper) 
and then pass that to asString() above.

The parsed version of the defines (using gcc -E) shows the expanded section 
as: (line breaks added)

typedef enum { RED = 0, GREEN = 1, BLUE = 87, }Color; 

const char* asString(Color n) { 
  switch (n) { 
     case RED:      return "RED"; 
     case GREEN: return "GREEN"; 
     case BLUE:    return "BLUE"; 
     default: return ""; 
   } 
} 

Color 
fromString(const char* str) 
{ 
  if (strcmp(str, "RED") == 0) { return RED; } 
  if (strcmp(str, "GREEN") == 0) { return GREEN; }
  if (strcmp(str, "BLUE") == 0) { return BLUE; } 
  return 0; 
}

int main() {
    Color c = GREEN;
    printf("%d\n",c);
    printf("%s\n", asString(c));
    printf("%d\n", fromString("BLUE"));
}

Can anyone see problems with this solution? Are the defines correct C?

Do we want to use safe_strcmp?
Should the strings be translatable?
#define AS_STRING_CASE(name, value) \
    case name: return _(#name);
instead of return #name?

Comments? Problems?

-- 

Neil Williams
=============
http://www.dcglug.org.uk/
http://www.nosoftwarepatents.com/
http://sourceforge.net/projects/isbnsearch/
http://www.neil.williamsleesmill.me.uk/
http://www.biglumber.com/x/web?qs=0x8801094A28BCB3E3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20050324/7b8f260b/attachment.bin


More information about the gnucash-devel mailing list