ccn_extend_dict.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025
00026 #include <ccn/charbuf.h>
00027 #include <ccn/extend_dict.h>
00028
00029 static int
00030 qsort_compare_dict_names(const void *x, const void *y)
00031 {
00032 const struct ccn_dict_entry *ex = x;
00033 const struct ccn_dict_entry *ey = y;
00034 return (strcmp(ex->name, ey->name));
00035 }
00036
00037
00038
00039
00040
00041 static int
00042 qsort_compare_dict_indices(const void *x, const void *y)
00043 {
00044 const struct ccn_dict_entry *ex = x;
00045 const struct ccn_dict_entry *ey = y;
00046 if (ex->name == NULL)
00047 return ((ey->name == NULL) ? 0 : 1);
00048 if (ey->name == NULL) return (-1);
00049 if (ex->index == ey->index) return (0);
00050 return ((ex->index < ey->index) ? -1 : 1);
00051 }
00052
00053
00054
00055
00056
00057
00058 void
00059 ccn_destroy_dict(struct ccn_dict **dp)
00060 {
00061 struct ccn_dict *d = *dp;
00062 int i;
00063 if (d != NULL) {
00064 for (i = 0; i < d->count; i++) {
00065 if (d->dict[i].name != NULL)
00066 free((void *)d->dict[i].name);
00067 }
00068 free(d);
00069 }
00070 *dp = NULL;
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 int
00084 ccn_extend_dict(const char *dict_file, struct ccn_dict *d, struct ccn_dict **rdp)
00085 {
00086 FILE *df = NULL;
00087 int i, c;
00088 struct ccn_dict_entry *ndd = NULL;
00089 int ndc = 0;
00090 struct ccn_charbuf *enamebuf = NULL;
00091 unsigned int eindex = 0;;
00092 struct ccn_dict *nd = NULL;
00093 enum scanner_state {
00094 S_OVERFLOW = -2,
00095 S_ERROR = -1,
00096 S_INITIAL = 0,
00097 S_INDEX = 1,
00098 S_NAME = 2,
00099 S_FLUSH = 3
00100 } s = S_INITIAL;
00101
00102 if (rdp == NULL)
00103 return (-1);
00104
00105 enamebuf = ccn_charbuf_create();
00106 if (enamebuf == NULL)
00107 return (-1);
00108
00109 df = fopen(dict_file, "r");
00110 if (df == NULL)
00111 goto err;
00112
00113
00114
00115 if (d) {
00116 ndd = calloc(d->count, sizeof(*(d->dict)));
00117 for (ndc = 0; ndc < d->count; ndc++) {
00118 ndd[ndc].index = d->dict[ndc].index;
00119 ndd[ndc].name = strdup(d->dict[ndc].name);
00120 }
00121 }
00122
00123
00124 while ((c = fgetc(df)) != EOF && s >= S_INITIAL) {
00125 switch (s) {
00126 case S_INITIAL:
00127 if (isdigit(c)) {
00128 s = S_INDEX;
00129 eindex = c - '0';
00130 } else
00131 s = S_ERROR;
00132 break;
00133 case S_INDEX:
00134 if (isdigit(c)) {
00135 unsigned int teindex = eindex;
00136 eindex = 10 * eindex + (c - '0');
00137 if (eindex < teindex)
00138 s = S_OVERFLOW;
00139 } else if (c == ',')
00140 s = S_NAME;
00141 else
00142 s = S_ERROR;
00143 break;
00144 case S_NAME:
00145 if (isalnum(c)) {
00146 ccn_charbuf_append_value(enamebuf, c, 1);
00147 } else if (c == ',' || c == '\n') {
00148
00149 ndd = realloc(ndd, sizeof(*ndd) * (ndc + 1));
00150 ndd[ndc].index = eindex;
00151 ndd[ndc].name = strdup(ccn_charbuf_as_string(enamebuf));
00152 ndc++;
00153 ccn_charbuf_reset(enamebuf);
00154 s = (c == ',') ? S_FLUSH : S_INITIAL;
00155 } else
00156 s = S_ERROR;
00157 break;
00158 case S_FLUSH:
00159 if (c == '\n')
00160 s = S_INITIAL;
00161 break;
00162 default:
00163 break;
00164 }
00165 }
00166 fclose(df);
00167 df = NULL;
00168
00169
00170 if (s < 0 || s == S_INDEX)
00171 goto err;
00172 else if (s == S_NAME) {
00173 ndd = realloc(ndd, sizeof(*ndd) * (ndc + 1));
00174 ndd[ndc].index = eindex;
00175 ndd[ndc].name = strdup(ccn_charbuf_as_string(enamebuf));
00176 ndc++;
00177 }
00178 ccn_charbuf_destroy(&enamebuf);
00179
00180
00181 qsort(ndd, ndc, sizeof(*ndd), qsort_compare_dict_names);
00182 for (i = 1; i < ndc; i++) {
00183 if (strcmp(ndd[i-1].name, ndd[i].name) == 0) {
00184 if (ndd[i-1].index == ndd[i].index) {
00185 free((void *)ndd[i-1].name);
00186 ndd[i-1].name = NULL;
00187 } else
00188 goto err;
00189 }
00190 }
00191
00192
00193
00194
00195 qsort(ndd, ndc, sizeof(*ndd), qsort_compare_dict_indices);
00196 for (i = 1; i < ndc; i++) {
00197 if (ndd[i].name == NULL) {
00198 ndc = i;
00199 ndd = realloc(ndd, sizeof(*ndd) * ndc);
00200 break;
00201 }
00202 if (ndd[i-1].index == ndd[i].index)
00203 goto err;
00204 }
00205
00206
00207 nd = calloc(1, sizeof(*nd));
00208 if (nd == NULL)
00209 goto err;
00210 nd->dict = ndd;
00211 nd->count = ndc;
00212 *rdp = nd;
00213 return (0);
00214
00215 err:
00216 ccn_charbuf_destroy(&enamebuf);
00217 if (df != NULL)
00218 fclose(df);
00219 if (ndd != NULL) {
00220 for (ndc--; ndc >= 0; ndc--) {
00221 free((void *)ndd[ndc].name);
00222 }
00223 }
00224 return (-1);
00225
00226 }