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 struct ccn_dict_entry *ndd_tmp = NULL;
00090 int ndc = 0;
00091 struct ccn_charbuf *enamebuf = NULL;
00092 unsigned int eindex = 0;;
00093 struct ccn_dict *nd = NULL;
00094 enum scanner_state {
00095 S_OVERFLOW = -2,
00096 S_ERROR = -1,
00097 S_INITIAL = 0,
00098 S_INDEX = 1,
00099 S_NAME = 2,
00100 S_FLUSH = 3
00101 } s = S_INITIAL;
00102
00103 if (rdp == NULL)
00104 return (-1);
00105
00106 enamebuf = ccn_charbuf_create();
00107 if (enamebuf == NULL)
00108 return (-1);
00109
00110 df = fopen(dict_file, "r");
00111 if (df == NULL)
00112 goto err;
00113
00114
00115
00116 if (d) {
00117 ndd = calloc(d->count, sizeof(*(d->dict)));
00118 for (ndc = 0; ndc < d->count; ndc++) {
00119 ndd[ndc].index = d->dict[ndc].index;
00120 ndd[ndc].name = strdup(d->dict[ndc].name);
00121 }
00122 }
00123
00124
00125 while ((c = fgetc(df)) != EOF && s >= S_INITIAL) {
00126 switch (s) {
00127 case S_INITIAL:
00128 if (isdigit(c)) {
00129 s = S_INDEX;
00130 eindex = c - '0';
00131 } else
00132 s = S_ERROR;
00133 break;
00134 case S_INDEX:
00135 if (isdigit(c)) {
00136 unsigned int teindex = eindex;
00137 eindex = 10 * eindex + (c - '0');
00138 if (eindex < teindex)
00139 s = S_OVERFLOW;
00140 } else if (c == ',')
00141 s = S_NAME;
00142 else
00143 s = S_ERROR;
00144 break;
00145 case S_NAME:
00146 if (isalnum(c)) {
00147 ccn_charbuf_append_value(enamebuf, c, 1);
00148 } else if (c == ',' || c == '\n') {
00149
00150 ndd_tmp = realloc(ndd, sizeof(*ndd) * (ndc + 1));
00151 if (ndd_tmp == NULL)
00152 goto err;
00153 ndd = ndd_tmp;
00154 ndd[ndc].index = eindex;
00155 ndd[ndc].name = strdup(ccn_charbuf_as_string(enamebuf));
00156 ndc++;
00157 ccn_charbuf_reset(enamebuf);
00158 s = (c == ',') ? S_FLUSH : S_INITIAL;
00159 } else
00160 s = S_ERROR;
00161 break;
00162 case S_FLUSH:
00163 if (c == '\n')
00164 s = S_INITIAL;
00165 break;
00166 default:
00167 break;
00168 }
00169 }
00170 fclose(df);
00171 df = NULL;
00172
00173
00174 if (s < 0 || s == S_INDEX)
00175 goto err;
00176 else if (s == S_NAME) {
00177 ndd_tmp = realloc(ndd, sizeof(*ndd) * (ndc + 1));
00178 if (ndd_tmp == NULL)
00179 goto err;
00180 ndd = ndd_tmp;
00181 ndd[ndc].index = eindex;
00182 ndd[ndc].name = strdup(ccn_charbuf_as_string(enamebuf));
00183 ndc++;
00184 }
00185 ccn_charbuf_destroy(&enamebuf);
00186
00187
00188 qsort(ndd, ndc, sizeof(*ndd), qsort_compare_dict_names);
00189 for (i = 1; i < ndc; i++) {
00190 if (strcmp(ndd[i-1].name, ndd[i].name) == 0) {
00191 if (ndd[i-1].index == ndd[i].index) {
00192 free((void *)ndd[i-1].name);
00193 ndd[i-1].name = NULL;
00194 } else
00195 goto err;
00196 }
00197 }
00198
00199
00200
00201
00202 qsort(ndd, ndc, sizeof(*ndd), qsort_compare_dict_indices);
00203 for (i = 1; i < ndc; i++) {
00204 if (ndd[i].name == NULL) {
00205 ndc = i;
00206 ndd_tmp = realloc(ndd, sizeof(*ndd) * ndc);
00207 if (ndd_tmp == NULL)
00208 goto err;
00209 ndd = ndd_tmp;
00210 break;
00211 }
00212 if (ndd[i-1].index == ndd[i].index)
00213 goto err;
00214 }
00215
00216
00217 nd = calloc(1, sizeof(*nd));
00218 if (nd == NULL)
00219 goto err;
00220 nd->dict = ndd;
00221 nd->count = ndc;
00222 *rdp = nd;
00223 return (0);
00224
00225 err:
00226 ccn_charbuf_destroy(&enamebuf);
00227 if (df != NULL)
00228 fclose(df);
00229 if (ndd != NULL) {
00230 for (ndc--; ndc >= 0; ndc--) {
00231 free((void *)ndd[ndc].name);
00232 }
00233 free(ndd);
00234 }
00235 return (-1);
00236
00237 }