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
00033
00034
00035
00036
00037
00038 #ifdef _WIN32
00039 #include "winconfig.h"
00040 #else
00041 #include "config.h"
00042 #endif
00043 #include "mxml.h"
00044
00045
00046
00047
00048
00049
00050 static int index_compare(mxml_index_t *ind, mxml_node_t *first,
00051 mxml_node_t *second);
00052 static int index_find(mxml_index_t *ind, const char *element,
00053 const char *value, mxml_node_t *node);
00054 static void index_sort(mxml_index_t *ind, int left, int right);
00055
00056
00057
00058
00059
00060
00061 void
00062 mxmlIndexDelete(mxml_index_t *ind)
00063 {
00064
00065
00066
00067
00068 if (!ind)
00069 return;
00070
00071
00072
00073
00074
00075 if (ind->attr)
00076 free(ind->attr);
00077
00078 if (ind->alloc_nodes)
00079 free(ind->nodes);
00080
00081 free(ind);
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091 mxml_node_t *
00092 mxmlIndexEnum(mxml_index_t *ind)
00093 {
00094
00095
00096
00097
00098 if (!ind)
00099 return (NULL);
00100
00101
00102
00103
00104
00105 if (ind->cur_node < ind->num_nodes)
00106 return (ind->nodes[ind->cur_node ++]);
00107 else
00108 return (NULL);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 mxml_node_t *
00122 mxmlIndexFind(mxml_index_t *ind,
00123 const char *element,
00124 const char *value)
00125 {
00126 int diff,
00127 current,
00128 first,
00129 last;
00130
00131
00132 #ifdef DEBUG
00133 printf("mxmlIndexFind(ind=%p, element=\"%s\", value=\"%s\")\n",
00134 ind, element ? element : "(null)", value ? value : "(null)");
00135 #endif
00136
00137
00138
00139
00140
00141 if (!ind || (!ind->attr && value))
00142 {
00143 #ifdef DEBUG
00144 puts(" returning NULL...");
00145 printf(" ind->attr=\"%s\"\n", ind->attr ? ind->attr : "(null)");
00146 #endif
00147
00148 return (NULL);
00149 }
00150
00151
00152
00153
00154
00155
00156 if (!element && !value)
00157 return (mxmlIndexEnum(ind));
00158
00159
00160
00161
00162
00163 if (!ind->num_nodes)
00164 {
00165 #ifdef DEBUG
00166 puts(" returning NULL...");
00167 puts(" no nodes!");
00168 #endif
00169
00170 return (NULL);
00171 }
00172
00173
00174
00175
00176
00177 if (ind->cur_node == 0)
00178 {
00179
00180
00181
00182
00183 first = 0;
00184 last = ind->num_nodes - 1;
00185
00186 #ifdef DEBUG
00187 printf(" find first time, num_nodes=%d...\n", ind->num_nodes);
00188 #endif
00189
00190 while ((last - first) > 1)
00191 {
00192 current = (first + last) / 2;
00193
00194 #ifdef DEBUG
00195 printf(" first=%d, last=%d, current=%d\n", first, last, current);
00196 #endif
00197
00198 if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0)
00199 {
00200
00201
00202
00203
00204 #ifdef DEBUG
00205 puts(" match!");
00206 #endif
00207
00208 while (current > 0 &&
00209 !index_find(ind, element, value, ind->nodes[current - 1]))
00210 current --;
00211
00212 #ifdef DEBUG
00213 printf(" returning first match=%d\n", current);
00214 #endif
00215
00216
00217
00218
00219
00220 ind->cur_node = current + 1;
00221
00222 return (ind->nodes[current]);
00223 }
00224 else if (diff < 0)
00225 last = current;
00226 else
00227 first = current;
00228
00229 #ifdef DEBUG
00230 printf(" diff=%d\n", diff);
00231 #endif
00232 }
00233
00234
00235
00236
00237
00238 for (current = first; current <= last; current ++)
00239 if (!index_find(ind, element, value, ind->nodes[current]))
00240 {
00241
00242
00243
00244
00245 #ifdef DEBUG
00246 printf(" returning only match %d...\n", current);
00247 #endif
00248
00249 ind->cur_node = current + 1;
00250
00251 return (ind->nodes[current]);
00252 }
00253
00254
00255
00256
00257
00258 ind->cur_node = ind->num_nodes;
00259
00260 #ifdef DEBUG
00261 puts(" returning NULL...");
00262 #endif
00263
00264 return (NULL);
00265 }
00266 else if (ind->cur_node < ind->num_nodes &&
00267 !index_find(ind, element, value, ind->nodes[ind->cur_node]))
00268 {
00269
00270
00271
00272
00273 #ifdef DEBUG
00274 printf(" returning next match %d...\n", ind->cur_node);
00275 #endif
00276
00277 return (ind->nodes[ind->cur_node ++]);
00278 }
00279
00280
00281
00282
00283
00284 ind->cur_node = ind->num_nodes;
00285
00286 #ifdef DEBUG
00287 puts(" returning NULL...");
00288 #endif
00289
00290 return (NULL);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 mxml_index_t *
00305 mxmlIndexNew(mxml_node_t *node,
00306 const char *element,
00307 const char *attr)
00308 {
00309 mxml_index_t *ind;
00310 mxml_node_t *current,
00311 **temp;
00312
00313
00314
00315
00316
00317
00318 #ifdef DEBUG
00319 printf("mxmlIndexNew(node=%p, element=\"%s\", attr=\"%s\")\n",
00320 node, element ? element : "(null)", attr ? attr : "(null)");
00321 #endif
00322
00323 if (!node)
00324 return (NULL);
00325
00326
00327
00328
00329
00330 if ((ind = (mxml_index_t*)calloc(1, sizeof(mxml_index_t))) == NULL)
00331 {
00332 mxml_error("Unable to allocate %d bytes for index - %s",
00333 sizeof(mxml_index_t), strerror(errno));
00334 return (NULL);
00335 }
00336
00337 if (attr)
00338 ind->attr = strdup(attr);
00339
00340 if (!element && !attr)
00341 current = node;
00342 else
00343 current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND);
00344
00345 while (current)
00346 {
00347 if (ind->num_nodes >= ind->alloc_nodes)
00348 {
00349 if (!ind->alloc_nodes)
00350 temp = (mxml_node_t**)malloc(64 * sizeof(mxml_node_t *));
00351 else
00352 temp = (mxml_node_t**)realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));
00353
00354 if (!temp)
00355 {
00356
00357
00358
00359
00360 mxml_error("Unable to allocate %d bytes for index: %s",
00361 (ind->alloc_nodes + 64) * sizeof(mxml_node_t *),
00362 strerror(errno));
00363
00364 mxmlIndexDelete(ind);
00365 return (NULL);
00366 }
00367
00368 ind->nodes = temp;
00369 ind->alloc_nodes += 64;
00370 }
00371
00372 ind->nodes[ind->num_nodes ++] = current;
00373
00374 current = mxmlFindElement(current, node, element, attr, NULL, MXML_DESCEND);
00375 }
00376
00377
00378
00379
00380
00381 #ifdef DEBUG
00382 {
00383 int i;
00384
00385
00386 printf("%d node(s) in index.\n\n", ind->num_nodes);
00387
00388 if (attr)
00389 {
00390 printf("Node Address Element %s\n", attr);
00391 puts("-------- -------- -------------- ------------------------------");
00392
00393 for (i = 0; i < ind->num_nodes; i ++)
00394 printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
00395 ind->nodes[i]->value.element.name,
00396 mxmlElementGetAttr(ind->nodes[i], attr));
00397 }
00398 else
00399 {
00400 puts("Node Address Element");
00401 puts("-------- -------- --------------");
00402
00403 for (i = 0; i < ind->num_nodes; i ++)
00404 printf("%8d %-8p %s\n", i, ind->nodes[i],
00405 ind->nodes[i]->value.element.name);
00406 }
00407
00408 putchar('\n');
00409 }
00410 #endif
00411
00412 if (ind->num_nodes > 1)
00413 index_sort(ind, 0, ind->num_nodes - 1);
00414
00415 #ifdef DEBUG
00416 {
00417 int i;
00418
00419
00420 puts("After sorting:\n");
00421
00422 if (attr)
00423 {
00424 printf("Node Address Element %s\n", attr);
00425 puts("-------- -------- -------------- ------------------------------");
00426
00427 for (i = 0; i < ind->num_nodes; i ++)
00428 printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
00429 ind->nodes[i]->value.element.name,
00430 mxmlElementGetAttr(ind->nodes[i], attr));
00431 }
00432 else
00433 {
00434 puts("Node Address Element");
00435 puts("-------- -------- --------------");
00436
00437 for (i = 0; i < ind->num_nodes; i ++)
00438 printf("%8d %-8p %s\n", i, ind->nodes[i],
00439 ind->nodes[i]->value.element.name);
00440 }
00441
00442 putchar('\n');
00443 }
00444 #endif
00445
00446
00447
00448
00449
00450 return (ind);
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 mxml_node_t *
00463 mxmlIndexReset(mxml_index_t *ind)
00464 {
00465 #ifdef DEBUG
00466 printf("mxmlIndexReset(ind=%p)\n", ind);
00467 #endif
00468
00469
00470
00471
00472
00473 if (!ind)
00474 return (NULL);
00475
00476
00477
00478
00479
00480 ind->cur_node = 0;
00481
00482
00483
00484
00485
00486 if (ind->num_nodes)
00487 return (ind->nodes[0]);
00488 else
00489 return (NULL);
00490 }
00491
00492
00493
00494
00495
00496
00497 static int
00498 index_compare(mxml_index_t *ind,
00499 mxml_node_t *first,
00500 mxml_node_t *second)
00501 {
00502 int diff;
00503
00504
00505
00506
00507
00508
00509 if ((diff = strcmp(first->value.element.name,
00510 second->value.element.name)) != 0)
00511 return (diff);
00512
00513
00514
00515
00516
00517 if (ind->attr)
00518 {
00519 if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr),
00520 mxmlElementGetAttr(second, ind->attr))) != 0)
00521 return (diff);
00522 }
00523
00524
00525
00526
00527
00528 return (0);
00529 }
00530
00531
00532
00533
00534
00535
00536 static int
00537 index_find(mxml_index_t *ind,
00538 const char *element,
00539 const char *value,
00540 mxml_node_t *node)
00541 {
00542 int diff;
00543
00544
00545
00546
00547
00548
00549 if (element)
00550 {
00551 if ((diff = strcmp(element, node->value.element.name)) != 0)
00552 return (diff);
00553 }
00554
00555
00556
00557
00558
00559 if (value)
00560 {
00561 if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0)
00562 return (diff);
00563 }
00564
00565
00566
00567
00568
00569 return (0);
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579 static void
00580 index_sort(mxml_index_t *ind,
00581 int left,
00582 int right)
00583 {
00584 mxml_node_t *pivot,
00585 *temp;
00586 int templ,
00587 tempr;
00588
00589
00590
00591
00592
00593
00594 do
00595 {
00596
00597
00598
00599
00600 pivot = ind->nodes[left];
00601
00602 for (templ = left, tempr = right; templ < tempr;)
00603 {
00604
00605
00606
00607
00608 while ((templ < right) &&
00609 index_compare(ind, ind->nodes[templ], pivot) <= 0)
00610 templ ++;
00611
00612
00613
00614
00615
00616 while ((tempr > left) &&
00617 index_compare(ind, ind->nodes[tempr], pivot) > 0)
00618 tempr --;
00619
00620
00621
00622
00623
00624 if (templ < tempr)
00625 {
00626 temp = ind->nodes[templ];
00627 ind->nodes[templ] = ind->nodes[tempr];
00628 ind->nodes[tempr] = temp;
00629 }
00630 }
00631
00632
00633
00634
00635
00636
00637 if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
00638 {
00639 ind->nodes[left] = ind->nodes[tempr];
00640 ind->nodes[tempr] = pivot;
00641 }
00642
00643
00644
00645
00646
00647 if (left < (tempr - 1))
00648 index_sort(ind, left, tempr - 1);
00649 }
00650 while (right > (left = tempr + 1));
00651 }
00652
00653
00654
00655
00656