wftk_value_isnull
and wftk_value_makenull
functions.
(May 13, 2002): since a lot of the value handling aspects of the original wftk have been rolled into the xmlobj
module of the XMLAPI, most of the wftk_value API is now just a wrapper for that. The only reason it's even a wrapper instead
of simply being replaced is that the wftk stores its context in the session, whereas xmlobj expects an explicit list definition to be
given. In the case that wftk is being used in tandem with the repository manager, then each datasheet
will contain the name of its list definition, and the repository can be asked for the definition of the list. The xmlobj needn't know
any of these details, but wftk does.
First off, let's define how the wftk finds its list. Here is the first place I'm going to make it explicit that the wftk core can
be compiled either in a repmgr context or not. The wftk command-line utility will not be repmgr-dependent, just for the record.
The idea there is to be very compact.
#ifdef WFTK_WITH_REPMGR XML * wftk_value_findlist (XML * session, XML * datasheet) { XML * repos; repos = session; while (xml_parent (repos)) repos = xml_parent(repos); return repos_defn (repos, xml_attrval (datasheet, "list")); } #else #define wftk_value_findlist(session, datasheet) (NULL) #endif |
WFTK_EXPORT XML * wftk_value_find (XML * session, XML * datasheet, const char * name) { return xmlobj_is_field (datasheet, wftk_value_findlist (session, datasheet), name); } WFTK_EXPORT XML * wftk_value_make (XML * session, XML * datasheet, const char * name) { return xmlobj_field (datasheet, wftk_value_findlist (session, datasheet), name); } WFTK_EXPORT char * wftk_value_get (XML * session, XML * datasheet, const char * name) { XML * data; WFTK_ADAPTOR * ad; if (!name) return NULL; if (*name == '!') return _wftk_value_special (session, datasheet, name); if (strchr (name, ':')) { ad = wftk_get_adaptor (session, DATASTORE, name); if (!ad) return ""; data = wftk_call_adaptor (ad, "get", datasheet, name); wftk_free_adaptor (session, ad); return (xmlobj_get_direct (data)); } data = wftk_value_find (session, datasheet, name); if (!data) return NULL; if (!strcmp (xml_attrval (data, "null"), "yes")) return NULL; return (xmlobj_get_direct (data)); } WFTK_EXPORT int wftk_value_get_num (XML * session, XML * datasheet, const char * name) { const char * value; int ret; if (!name) return 0; value = wftk_value_get (session, datasheet, name); if (!value) return 0; ret = atoi (value); free (value); return ret; } WFTK_EXPORT int wftk_value_isnull (XML * session, XML * datasheet, const char * name) { XML * data; WFTK_ADAPTOR * ad; if (!name) return 1; /* Null name is, well, null. Logical, right? */ if (*name == '!') return 0; /* Special value is never null. Why? Because I say so. */ data = wftk_value_find (session, datasheet, name); if (!data) return 1; if (!strcmp (xml_attrval (data, "null"), "yes")) return 1; return 0; } WFTK_EXPORT int wftk_value_set (XML * session, XML * datasheet, const char * name, const char * value) { XML * data; char * stuff; WFTK_ADAPTOR * ad; if (!name) return 0; if (*name == '!') return 0; /* Refuse to set special values. */ if (strchr (name, ':')) { ad = wftk_get_adaptor (session, DATASTORE, name); if (!ad) return 0; wftk_call_adaptor (ad, "set", datasheet, name, value); wftk_free_adaptor (session, ad); return 1; } data = wftk_value_make (session, datasheet, name); if (!data) return 0; xmlobj_set_direct (data, value); if (!strcmp (xml_attrval (data, "null"), "yes")) xml_set (data, "null", ""); /* 07/22/01 - implementing data aliasing (local cache of remote data) with write-though. */ if (*xml_attrval (data, "storage")) { ad = wftk_get_adaptor (session, DATASTORE, xml_attrval (data, "storage")); if (ad) { wftk_call_adaptor (ad, "store", data); wftk_free_adaptor (session, ad); } } return 1; } WFTK_EXPORT int wftk_value_set_num (XML * session, XML * datasheet, const char * name, int value) { XML * data; WFTK_ADAPTOR * ad; char valbuf[sizeof(int) * 3 + 1]; if (!name) return 0; if (*name == '!') return 0; sprintf (valbuf, "%d", value); return (wftk_value_set (session, datasheet, name, valbuf)); } WFTK_EXPORT int wftk_value_makenull (XML * session, XML * datasheet, const char * name) { XML * data; WFTK_ADAPTOR * ad; if (!name) return 0; if (*name == '!') return 0; /* Refuse to set special values. */ if (strchr (name, ':')) { ad = wftk_get_adaptor (session, DATASTORE, name); if (!ad) return 0; wftk_call_adaptor (ad, "makenull", datasheet, name); wftk_free_adaptor (session, ad); return 1; } data = wftk_value_make (session, datasheet, name); if (!data) return 0; xml_set (data, "null", "yes"); return 1; } |
sprintf
-like affair, which
takes a string and replaces named values in it which are marked like ${this}
. Later we'll need boolean
expressions and stuff, and that will also probably fall into this value area.
July 18, 2001: Finally got around to building a version of the interpreter which builds
its value as it goes (via malloc, or more specifically, via XMLAPI's xml_attrcat). This resolves
a lot of the fixed-buffer issues I had with the earlier code.
wftk_value_interpret
returns the number of bytes it copied to the buffer.wftk_value_interpreta
returns a new buffer. You're on your own for deallocation.
WFTK_EXPORT int wftk_value_interpret (XML * session, XML * datasheet, const char * spec, char * buffer, int bufsize) { int count = 0; const char *value; char namebuf[256]; int i; bufsize--; /* Leave room for the null. */ while (*spec) { if (spec[0] == '$' && spec[1] == '{') { i = 0; spec += 2; while (*spec && *spec != '}' && i < sizeof(namebuf) - 1) { namebuf[i++] = *spec++; } if (*spec == '}') spec++; namebuf[i] = '\0'; value = wftk_value_get (session, datasheet, namebuf); if (value) { while (*value && bufsize) { *buffer++ = *value++; count++; bufsize--; } free (value); } } else { *buffer++ = *spec++; count++; bufsize--; } if (!bufsize) break; } *buffer = '\0'; return count; } WFTK_EXPORT char * wftk_value_interpreta (XML * session, XML * datasheet, const char * spec) { int count = 0; char *value; char * mark; char namebuf[256]; int len; int i; XML * val; mark = strstr (spec, "${"); if (!mark) return strdup (spec); /* Easy case! No interpretation! */ val = xml_create ("value"); xml_set (val, "value", ""); while (mark) { xml_attrncat (val, "value", spec, mark - spec); spec = mark + 2; mark = strchr (spec, '}'); if (mark) { len = mark - spec; } else { len = strlen (spec); } if (len > sizeof (namebuf) - 1) len = sizeof (namebuf) - 1; strncpy (namebuf, spec, len); namebuf[len] = '\0'; value = wftk_value_get (session, datasheet, namebuf); if (value) { xml_attrcat (val, "value", value); free (value); } if (mark) { spec = mark + 1; mark = strstr (spec, "${"); } } xml_attrncat (val, "value", spec, mark - spec); value = strdup (xml_attrval (val, "value")); xml_free (val); return value; } |
char * _wftk_value_special (XML * session, XML * datasheet, const char * name) { struct tm * timeptr; time_t julian; char * ret; char * value; if (!strcmp (name, "!now")) { value = (char *) malloc (64); time (&julian); timeptr = localtime (&julian); sprintf (value, "%04d-%02d-%02d %02d:%02d:%02d", timeptr->tm_year + 1900, timeptr->tm_mon + 1, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); return (value); } return (NULL); } |
WFTK_EXPORT int wftk_value_settype (XML * session, XML * datasheet, const char * name, const char * type) { XML * data; WFTK_ADAPTOR * ad; if (!name) return 0; if (*name == '!') return 0; /* Refuse to set special values. */ if (strchr (name, ':')) return 0; /* Can't set types for alternate stores -- the answer will be aliases, later. */ data = wftk_value_make (session, datasheet, name); if (!data) return 0; xml_set (data, "type", type); return 1; } WFTK_EXPORT int wftk_value_define (XML * session, XML * datasheet, const char * name, const char * storage) { XML * data; data = wftk_value_make (session, datasheet, name); if (data) { xml_set (data, "storage", storage); } } |
wftk_value_calc
just runs wftk_value_interpret
on its incoming value and sets the named value accordingly.
WFTK_EXPORT int wftk_value_calc (XML * session, XML * datasheet, const char * name, const char * value) { return 0; } |
WFTK_EXPORT XML * wftk_value_html (XML * session, XML * datasheet, const char * name) { XML * field; XML * data; WFTK_ADAPTOR * ad; if (!name) return 0; if (*name == '!') return (xml_createtext_nodup (_wftk_value_special (session, datasheet, name))); if (strchr (name, ':')) { ad = wftk_get_adaptor (session, DATASTORE, name); if (!ad) return 0; data = wftk_call_adaptor (ad, "get", datasheet, name); wftk_free_adaptor (session, ad); field = xml_create ("input"); xml_set (field, "name", name); xml_set (field, "value", xml_attrval (data, "value")); xml_delete (data); return (field); } data = wftk_value_find (session, datasheet, name); if (!data) { field = xml_create ("input"); xml_set (field, "name", name); xml_set (field, "value", ""); return (field); } if (*xml_attrval (data, "type")) { ad = wftk_get_adaptor (session, DATATYPE, xml_attrval (data, "type")); if (ad) { field = wftk_call_adaptor (ad, "html", datasheet, data); wftk_free_adaptor (session, ad); return (field); } } field = xml_create ("input"); xml_set (field, "name", name); if (*xml_attrval (data, "size")) { xml_set (field, "size", xml_attrval (data, "size")); } if (!strcmp (xml_attrval (data, "null"), "yes")) { xml_set (field, "value", ""); } else { xml_set_nodup (field, "value", wftk_value_get (session, datasheet, name)); } return (field); } WFTK_EXPORT XML * wftk_value_htmlblank (XML * session, XML * datasheet, const char * name) { XML * field; XML * data; WFTK_ADAPTOR * ad; if (!name) return 0; if (*name == '!') return (xml_createtext_nodup (_wftk_value_special (session, datasheet, name))); if (strchr (name, ':')) { field = xml_create ("input"); xml_set (field, "name", name); xml_set (field, "value", ""); return (field); } data = wftk_value_find (session, datasheet, name); if (!data) { field = xml_create ("input"); xml_set (field, "name", name); xml_set (field, "value", ""); return (field); } if (*xml_attrval (data, "type")) { ad = wftk_get_adaptor (session, DATATYPE, xml_attrval (data, "type")); if (ad) { field = wftk_call_adaptor (ad, "htmlblank", datasheet, data); wftk_free_adaptor (session, ad); return (field); } } field = xml_create ("input"); xml_set (field, "name", name); if (*xml_attrval (data, "size")) { xml_set (field, "size", xml_attrval (data, "size")); } xml_set (field, "value", ""); return (field); } |
WFTK_EXPORT int wftk_value_list (XML * session, XML * datasheet, XML * list) { int counter = 0; XML * pointer = xml_firstelem (datasheet); XML * value; if (!list) return 0; while (pointer) { if (xml_is (pointer, "field")) { counter++; value = xml_create ("field"); xml_set (value, "id", xml_attrval (pointer, "id")); xml_set_nodup (value, "value", xmlobj_get_direct (pointer)); xml_set (value, "type", xml_attrval (pointer, "type")); xml_append (list, value); } pointer = xml_nextelem (pointer); } xml_setnum (list, "count", counter); return counter; } WFTK_EXPORT XML * wftk_value_info (XML * session, XML * datasheet, const char * name) { return 0; } |
WFTK_EXPORT int wftk_value_counter (XML * session, XML * datasheet, const char * name) { int count; XML * state; state = xml_loc (datasheet, ".state"); if (!state) { state = xml_create ("state"); xml_append_pretty (datasheet, state); } count = atoi (xml_attrval (state, name)); count++; xml_setnum (state, name, count); return count; } |
This code and documentation are released under the terms of the GNU license. They are copyright (c) 2000-2004, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. |