/* Public domain */ #define VAR_NAME_MAX 32 #define VAR_BUF_INIT 32 #define VAR_BUF_GROW 1024 /* User variable */ typedef struct var { char key[VAR_NAME_MAX]; /* Variable name */ char *value; /* Variable value */ size_t len; /* Length in characters */ size_t bufSize; /* Total buffer size */ int global; /* Persist across queries */ TAILQ_ENTRY(var) vars; } VAR; __BEGIN_DECLS VAR *VAR_SetGlobal(const char *, const char *, ...) FORMAT_ATTRIBUTE(__printf__, 2, 3); VAR *VAR_SetGlobalS(const char *, const char *); VAR *VAR_Set(const char *, const char *, ...) FORMAT_ATTRIBUTE(__printf__, 2, 3); VAR *VAR_SetS(const char *, const char *); VAR *VAR_SetS_NODUP(const char *, char *) NONNULL_ATTRIBUTE(2); void VAR_Cat(VAR *, const char *, ...) FORMAT_ATTRIBUTE(__printf__, 2, 3) NONNULL_ATTRIBUTE(2); void VAR_Unset(const char *) NONNULL_ATTRIBUTE(1); void VAR_Wipe(const char *) NONNULL_ATTRIBUTE(1); int VAR_Defined(const char *); void VAR_Free(VAR *); static __inline__ void VAR_CatS(VAR *, const char *) NONNULL_ATTRIBUTE(2); static __inline__ void VAR_CatS_NODUP(VAR *, char *) NONNULL_ATTRIBUTE(2); static __inline__ VAR * VAR_New(const char *key) { return VAR_SetS(key, NULL); } static __inline__ void VAR_Grow(VAR *var, size_t len) { if (var->len+len >= var->bufSize) { var->bufSize = var->len+len+VAR_BUF_GROW; var->value = CGI_Realloc(var->value, var->bufSize); } } static __inline__ void VAR_CatC(VAR *var, const char c) { VAR_Grow(var, 1); var->value[var->len] = c; var->value[var->len+1] = '\0'; var->len++; } static __inline__ void VAR_CatS(VAR *var, const char *s) { size_t len; len = strlen(s); VAR_Grow(var, len+1); memcpy(&var->value[var->len], s, len+1); var->len += len; } static __inline__ void VAR_CatS_NoHTML(VAR *var, const char *s) { const char *c; VAR_Grow(var, strlen(s)); for (c = &s[0]; *c != '\0'; c++) { if (*c == '"') { VAR_CatS(var, """); } else if (*c == '&') { VAR_CatS(var, "&"); } else if (*c == '<') { VAR_CatS(var, "<"); } else if (*c == '>') { VAR_CatS(var, ">"); } else { VAR_CatC(var, *c); } } } static __inline__ void VAR_CatS_NODUP(VAR *var, char *s) { size_t len; len = strlen(s); VAR_Grow(var, len+1); memcpy(&var->value[var->len], s, len+1); var->len += len; free(s); } static __inline__ void VAR_CatJS(VAR *var, const char *s) { const char *c; VAR_Grow(var, strlen(s)+3); VAR_CatC(var, '"'); for (c = &s[0]; *c != '\0'; c++) { if (*c == '\\') { VAR_CatS(var, "\\\\"); } else if (*c == '"') { VAR_CatS(var, "\\\""); } else { VAR_CatC(var, *c); } } VAR_CatS(var, "\","); } static __inline__ void VAR_CatJS_NODUP(VAR *var, char *s) { VAR_CatJS(var, s); free(s); } static __inline__ void VAR_CatJS_NoHTML(VAR *var, const char *s) { const char *c; VAR_Grow(var, strlen(s)+3); VAR_CatC(var, '"'); for (c = &s[0]; *c != '\0'; c++) { if (*c == '\\') { VAR_CatS(var, "\\\\"); } else if (*c == '"') { VAR_CatS(var, "\\\""); } else if (*c == '<') { VAR_CatS(var, "<"); } else if (*c == '>') { VAR_CatS(var, ">"); } else { VAR_CatC(var, *c); } } VAR_CatS(var, "\","); } static __inline__ void VAR_CatJS_NoHTML_NODUP(VAR *var, char *s) { VAR_CatJS_NoHTML(var, s); free(s); } static __inline__ void VAR_CatN(VAR *var, const char *s, size_t len) { VAR_Grow(var, len+1); memcpy(&var->value[var->len], s, len); var->value[var->len+len-1] = '\0'; var->len += len; } static __inline__ void VAR_CatN_NoNUL(VAR *var, const char *s, size_t len) { VAR_Grow(var, len+1); memcpy(&var->value[var->len], s, len); var->len += len; } /* TODO: Hash */ static __inline__ char * VAR_Get(const char *key) { VAR *var; TAILQ_FOREACH(var, &cgi->vars, vars) { if (var->key[0] != '\0' && strcmp(var->key, key) == 0) break; } return (var != NULL ? var->value : NULL); } /* Set an integer range (and collapse to a single integer if min=max). */ static __inline__ VAR * VAR_SetIntRange(const char *key, int min, int max) { VAR *v; if (min == max) { v = VAR_Set(key, "%d", min); } else { v = VAR_Set(key, "%d-%d", min, max); } return (v); } /* Set a float range (and collapse to a single number if min=max). */ static __inline__ VAR * VAR_SetFloatRange(const char *key, float min, float max) { VAR *v; if (min == max) { v = VAR_Set(key, "%.0f", min); } else { v = VAR_Set(key, "%.0f-%.0f", min, max); } return (v); } /* Set a double range (and collapse to a single number if min=max). */ static __inline__ VAR * VAR_SetDoubleRange(const char *key, double min, double max) { VAR *v; if (min == max) { v = VAR_Set(key, "%.0f", min); } else { v = VAR_Set(key, "%.0f-%.0f", min, max); } return (v); } __END_DECLS #if defined(_PERCGI_INTERNAL) || defined(_USE_PERCGI_VAR) #define Get VAR_Get #define Set VAR_Set #define SetS VAR_SetS #define SetS_NODUP VAR_SetS_NODUP #define Cat VAR_Cat #define CatS VAR_CatS #define CatS_NODUP VAR_CatS_NODUP #define CatS_NoHTML VAR_CatS_NoHTML #define CatJS VAR_CatJS #define CatJS_NODUP VAR_CatJS_NODUP #define CatJS_NoHTML VAR_CatJS_NoHTML #define CatJS_NoHTML_NoDUP VAR_CatJS_NoHTML #define CatN VAR_CatN #define CatN_NoNUL VAR_CatN_NoNUL #define CatC VAR_CatC #define SetGlobal VAR_SetGlobal #define SetGlobalS VAR_SetGlobalS #define SetIntRange VAR_SetIntRange #define SetFloatRange VAR_SetFloatRange #define SetDoubleRange VAR_SetDoubleRange #endif