00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef _ATTRS_H
00033 #define _ATTRS_H
00034
00035 #include <string.h>
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038 #include "../../usr_avp.h"
00039 #include "../../trim.h"
00040 #include "../../str.h"
00041 #include "../../ut.h"
00042
00043
00044
00045
00046
00047 static int parse_attrs(avp_ident_t** avps, int* avps_n, char* attrs)
00048 {
00049 str token;
00050
00051 token.s = strtok(attrs, ",");
00052
00053 *avps = 0;
00054 *avps_n = 0;
00055 while(token.s) {
00056 token.len = strlen(token.s);
00057 trim(&token);
00058
00059 if (token.len && token.s[0] == '$') {
00060 token.s++;
00061 token.len--;
00062 } else goto skip;
00063
00064 *avps = pkg_realloc(*avps, sizeof(avp_ident_t) * (*avps_n + 1));
00065 if (!*avps) {
00066 ERR("No memory left\n");
00067 goto err;
00068 }
00069
00070 if (parse_avp_ident(&token, &(*avps)[*avps_n]) < 0) {
00071 ERR("Error while parsing AVP id '%.*s'\n", token.len, ZSW(token.s));
00072 goto err;
00073 }
00074 DBG("Found attribute $%.*s\n", (*avps)[*avps_n].name.s.len, (*avps)[*avps_n].name.s.s);
00075
00076 (*avps_n)++;
00077 skip:
00078 token.s = strtok(0, ",");
00079 }
00080 return 0;
00081 err:
00082 if (*avps) pkg_free(*avps);
00083 return -1;
00084 }
00085
00086
00087
00088 #define attrs_append(dst, src) \
00089 do { \
00090 if ((dst).len < (src).len) { \
00091 ERR("Buffer too small\n"); \
00092 goto error; \
00093 } \
00094 memcpy((dst).s, (src).s, (src).len); \
00095 (dst).s += (src).len; \
00096 (dst).len -= (src).len; \
00097 } while(0)
00098
00099
00100
00101
00102
00103 #define attrs_append_esc(dst, src, esc_quote) \
00104 do { \
00105 int i; \
00106 char* w; \
00107 \
00108 if ((dst).len < ((src).len * 2)) { \
00109 ERR("Buffer too small\n"); \
00110 goto error; \
00111 } \
00112 \
00113 w = (dst).s; \
00114 for(i = 0; i < (src).len; i++) { \
00115 switch((src).s[i]) { \
00116 case '\n': *w++ = '\\'; *w++ = 'n'; break; \
00117 case '\r': *w++ = '\\'; *w++ = 'r'; break; \
00118 case '\t': *w++ = '\\'; *w++ = 't'; break; \
00119 case '\\': *w++ = '\\'; *w++ = '\\'; break; \
00120 case '\0': *w++ = '\\'; *w++ = '0'; break; \
00121 case '"': \
00122 if (esc_quote) { \
00123 *w++ = '\\'; *w++ = 'q'; \
00124 } else { \
00125 *w++ = (src).s[i]; \
00126 } \
00127 break; \
00128 case ':': *w++ = '\\'; *w++ = 'o'; break; \
00129 case ',': *w++ = '\\'; *w++ = 'c'; break; \
00130 default: *w++ = (src).s[i]; break; \
00131 } \
00132 } \
00133 (dst).len -= w - (dst).s; \
00134 (dst).s = w; \
00135 } while(0)
00136
00137
00138 #define attrs_append_printf(dst, fmt, args...) \
00139 do { \
00140 int len = snprintf((dst).s, (dst).len, (fmt), ## args); \
00141 if (len < 0 || len >= (dst).len) { \
00142 ERR("Buffer too small\n"); \
00143 goto error; \
00144 } \
00145 (dst).s += len; \
00146 (dst).len -= len; \
00147 } while(0)
00148
00149
00150
00151 #define ATTRS_BUF_LEN 4096
00152 static str* print_attrs(avp_ident_t* avps, int avps_n, int quote)
00153 {
00154 static str quote_s = STR_STATIC_INIT("\"");
00155 static str attrs_name_delim = STR_STATIC_INIT(":");
00156 static str attrs_delim = STR_STATIC_INIT(",");
00157 static char buf[ATTRS_BUF_LEN];
00158 static str res;
00159 int i;
00160 struct search_state st;
00161 avp_value_t val;
00162 str p;
00163
00164 p.s = buf;
00165 p.len = ATTRS_BUF_LEN - 1;
00166
00167 if (quote && avps_n) {
00168 attrs_append(p, quote_s);
00169 }
00170
00171 for(i = 0; i < avps_n; i++) {
00172 avp_t *this_avp = search_first_avp(avps[i].flags, avps[i].name, &val, &st);
00173 if (!this_avp) continue;
00174 attrs_append(p, avps[i].name.s);
00175 attrs_append(p, attrs_name_delim);
00176 if (this_avp->flags & AVP_VAL_STR)
00177 attrs_append_esc(p, val.s, quote);
00178 else
00179 attrs_append_printf(p, "%d", val.n);
00180
00181 while(search_next_avp(&st, &val)) {
00182 attrs_append(p, attrs_delim);
00183 attrs_append(p, avps[i].name.s);
00184 attrs_append(p, attrs_name_delim);
00185 attrs_append_esc(p, val.s, quote);
00186 }
00187 if (i < (avps_n - 1)) attrs_append(p, attrs_delim);
00188 }
00189
00190 if (quote && avps_n) {
00191 attrs_append(p, quote_s);
00192 }
00193
00194 *p.s = '\0';
00195 res.s = buf;
00196 res.len = p.s - buf;
00197 return &res;
00198
00199 error:
00200 return 0;
00201 }
00202
00203 #endif