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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "config.h"
00052 #include "mxml.h"
00053 #ifdef WIN32
00054 # include <io.h>
00055 #else
00056 # include <unistd.h>
00057 #endif
00058
00059
00060
00061
00062
00063
00064 #define ENCODE_UTF8 0
00065 #define ENCODE_UTF16BE 1
00066 #define ENCODE_UTF16LE 2
00067
00068
00069
00070
00071
00072
00073 #define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t')
00074
00075
00076
00077
00078
00079
00080 typedef struct mxml_fdbuf_s
00081 {
00082 int fd;
00083 unsigned char *current,
00084 *end,
00085 buffer[8192];
00086 } mxml_fdbuf_t;
00087
00088
00089
00090
00091
00092
00093 extern void (*mxml_error_cb)(const char *);
00094
00095
00096
00097
00098
00099
00100 static mxml_custom_load_cb_t mxml_custom_load_cb = NULL;
00101 static mxml_custom_save_cb_t mxml_custom_save_cb = NULL;
00102
00103
00104
00105
00106
00107
00108 static int mxml_add_char(int ch, char **ptr, char **buffer,
00109 int *bufsize);
00110 static int mxml_fd_getc(void *p, int *encoding);
00111 static int mxml_fd_putc(int ch, void *p);
00112 static int mxml_fd_read(mxml_fdbuf_t *buf);
00113 static int mxml_fd_write(mxml_fdbuf_t *buf);
00114 static int mxml_file_getc(void *p, int *encoding);
00115 static int mxml_file_putc(int ch, void *p);
00116 static int mxml_get_entity(mxml_node_t *parent, void *p,
00117 int *encoding,
00118 int (*getc_cb)(void *, int *));
00119 static mxml_node_t *mxml_load_data(mxml_node_t *top, void *p,
00120 mxml_type_t (*cb)(mxml_node_t *),
00121 int (*getc_cb)(void *, int *));
00122 static int mxml_parse_element(mxml_node_t *node, void *p,
00123 int *encoding,
00124 int (*getc_cb)(void *, int *));
00125 static int mxml_string_getc(void *p, int *encoding);
00126 static int mxml_string_putc(int ch, void *p);
00127 static int mxml_write_name(const char *s, void *p,
00128 int (*putc_cb)(int, void *));
00129 static int mxml_write_node(mxml_node_t *node, void *p,
00130 const char *(*cb)(mxml_node_t *, int),
00131 int col,
00132 int (*putc_cb)(int, void *));
00133 static int mxml_write_string(const char *s, void *p,
00134 int (*putc_cb)(int, void *));
00135 static int mxml_write_ws(mxml_node_t *node, void *p,
00136 const char *(*cb)(mxml_node_t *, int), int ws,
00137 int col, int (*putc_cb)(int, void *));
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 mxml_node_t *
00156 mxmlLoadFd(mxml_node_t *top,
00157 int fd,
00158 mxml_type_t (*cb)(mxml_node_t *node))
00159
00160 {
00161 mxml_fdbuf_t buf;
00162
00163
00164
00165
00166
00167
00168 buf.fd = fd;
00169 buf.current = buf.buffer;
00170 buf.end = buf.buffer;
00171
00172
00173
00174
00175
00176 return (mxml_load_data(top, &buf, cb, mxml_fd_getc));
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 mxml_node_t *
00196 mxmlLoadFile(mxml_node_t *top,
00197 FILE *fp,
00198 mxml_type_t (*cb)(mxml_node_t *node))
00199
00200 {
00201
00202
00203
00204
00205 return (mxml_load_data(top, fp, cb, mxml_file_getc));
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 mxml_node_t *
00225 mxmlLoadString(mxml_node_t *top,
00226 const char *s,
00227 mxml_type_t (*cb)(mxml_node_t *node))
00228
00229 {
00230
00231
00232
00233
00234 return (mxml_load_data(top, &s, cb, mxml_string_getc));
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 char *
00255 mxmlSaveAllocString(mxml_node_t *node,
00256 const char *(*cb)(mxml_node_t *node, int ws))
00257
00258 {
00259 int bytes;
00260 char buffer[8192];
00261 char *s;
00262
00263
00264
00265
00266
00267
00268 bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);
00269
00270 if (bytes <= 0)
00271 return (NULL);
00272
00273 if (bytes < (int)(sizeof(buffer) - 1))
00274 {
00275
00276
00277
00278
00279
00280 return (strdup(buffer));
00281 }
00282
00283
00284
00285
00286
00287
00288 if ((s = malloc(bytes + 1)) == NULL)
00289 return (NULL);
00290
00291 mxmlSaveString(node, s, bytes + 1, cb);
00292
00293
00294
00295
00296
00297 return (s);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 int
00312 mxmlSaveFd(mxml_node_t *node,
00313 int fd,
00314 const char *(*cb)(mxml_node_t *node, int ws))
00315
00316 {
00317 int col;
00318 mxml_fdbuf_t buf;
00319
00320
00321
00322
00323
00324
00325 buf.fd = fd;
00326 buf.current = buf.buffer;
00327 buf.end = buf.buffer + sizeof(buf.buffer) - 4;
00328
00329
00330
00331
00332
00333 if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc)) < 0)
00334 return (-1);
00335
00336 if (col > 0)
00337 if (mxml_fd_putc('\n', &buf) < 0)
00338 return (-1);
00339
00340
00341
00342
00343
00344 return (mxml_fd_write(&buf));
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 int
00359 mxmlSaveFile(mxml_node_t *node,
00360 FILE *fp,
00361 const char *(*cb)(mxml_node_t *node, int ws))
00362
00363 {
00364 int col;
00365
00366
00367
00368
00369
00370
00371 if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc)) < 0)
00372 return (-1);
00373
00374 if (col > 0)
00375 if (putc('\n', fp) < 0)
00376 return (-1);
00377
00378
00379
00380
00381
00382 return (0);
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 int
00401 mxmlSaveString(mxml_node_t *node,
00402 char *buffer,
00403 int bufsize,
00404 const char *(*cb)(mxml_node_t *node, int ws))
00405
00406 {
00407 int col;
00408 char *ptr[2];
00409
00410
00411
00412
00413
00414
00415 ptr[0] = buffer;
00416 ptr[1] = buffer + bufsize;
00417
00418 if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc)) < 0)
00419 return (-1);
00420
00421 if (col > 0)
00422 mxml_string_putc('\n', ptr);
00423
00424
00425
00426
00427
00428 if (ptr[0] >= ptr[1])
00429 buffer[bufsize - 1] = '\0';
00430 else
00431 ptr[0][0] = '\0';
00432
00433
00434
00435
00436
00437 return (ptr[0] - buffer);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 void
00453 mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
00454
00455 mxml_custom_save_cb_t save)
00456
00457 {
00458 mxml_custom_load_cb = load;
00459 mxml_custom_save_cb = save;
00460 }
00461
00462
00463
00464
00465
00466
00467 void
00468 mxmlSetErrorCallback(void (*cb)(const char *))
00469
00470 {
00471 mxml_error_cb = cb;
00472 }
00473
00474
00475
00476
00477
00478
00479 static int
00480 mxml_add_char(int ch,
00481 char **bufptr,
00482 char **buffer,
00483 int *bufsize)
00484 {
00485 char *newbuffer;
00486
00487
00488 if (*bufptr >= (*buffer + *bufsize - 4))
00489 {
00490
00491
00492
00493
00494 if (*bufsize < 1024)
00495 (*bufsize) *= 2;
00496 else
00497 (*bufsize) += 1024;
00498
00499 if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
00500 {
00501 free(*buffer);
00502
00503 mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
00504
00505 return (-1);
00506 }
00507
00508 *bufptr = newbuffer + (*bufptr - *buffer);
00509 *buffer = newbuffer;
00510 }
00511
00512 if (ch < 0x80)
00513 {
00514
00515
00516
00517
00518 *(*bufptr)++ = ch;
00519 }
00520 else if (ch < 0x800)
00521 {
00522
00523
00524
00525
00526 *(*bufptr)++ = 0xc0 | (ch >> 6);
00527 *(*bufptr)++ = 0x80 | (ch & 0x3f);
00528 }
00529 else if (ch < 0x10000)
00530 {
00531
00532
00533
00534
00535 *(*bufptr)++ = 0xe0 | (ch >> 12);
00536 *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
00537 *(*bufptr)++ = 0x80 | (ch & 0x3f);
00538 }
00539 else
00540 {
00541
00542
00543
00544
00545 *(*bufptr)++ = 0xf0 | (ch >> 18);
00546 *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
00547 *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
00548 *(*bufptr)++ = 0x80 | (ch & 0x3f);
00549 }
00550
00551 return (0);
00552 }
00553
00554
00555
00556
00557
00558
00559 static int
00560 mxml_fd_getc(void *p,
00561 int *encoding)
00562 {
00563 mxml_fdbuf_t *buf;
00564 int ch,
00565 temp;
00566
00567
00568
00569
00570
00571
00572 buf = (mxml_fdbuf_t *)p;
00573
00574 if (buf->current >= buf->end)
00575 if (mxml_fd_read(buf) < 0)
00576 return (EOF);
00577
00578 ch = *(buf->current)++;
00579
00580 switch (*encoding)
00581 {
00582 case ENCODE_UTF8 :
00583
00584
00585
00586
00587 if (!(ch & 0x80))
00588 {
00589 #if DEBUG > 1
00590 printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
00591 #endif
00592
00593 if (mxml_bad_char(ch))
00594 {
00595 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00596 ch);
00597 return (EOF);
00598 }
00599
00600 return (ch);
00601 }
00602 else if (ch == 0xfe)
00603 {
00604
00605
00606
00607
00608 if (buf->current >= buf->end)
00609 if (mxml_fd_read(buf) < 0)
00610 return (EOF);
00611
00612 ch = *(buf->current)++;
00613
00614 if (ch != 0xff)
00615 return (EOF);
00616
00617 *encoding = ENCODE_UTF16BE;
00618
00619 return (mxml_fd_getc(p, encoding));
00620 }
00621 else if (ch == 0xff)
00622 {
00623
00624
00625
00626
00627 if (buf->current >= buf->end)
00628 if (mxml_fd_read(buf) < 0)
00629 return (EOF);
00630
00631 ch = *(buf->current)++;
00632
00633 if (ch != 0xfe)
00634 return (EOF);
00635
00636 *encoding = ENCODE_UTF16LE;
00637
00638 return (mxml_fd_getc(p, encoding));
00639 }
00640 else if ((ch & 0xe0) == 0xc0)
00641 {
00642
00643
00644
00645
00646 if (buf->current >= buf->end)
00647 if (mxml_fd_read(buf) < 0)
00648 return (EOF);
00649
00650 temp = *(buf->current)++;
00651
00652 if ((temp & 0xc0) != 0x80)
00653 return (EOF);
00654
00655 ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
00656
00657 if (ch < 0x80)
00658 return (EOF);
00659 }
00660 else if ((ch & 0xf0) == 0xe0)
00661 {
00662
00663
00664
00665
00666 if (buf->current >= buf->end)
00667 if (mxml_fd_read(buf) < 0)
00668 return (EOF);
00669
00670 temp = *(buf->current)++;
00671
00672 if ((temp & 0xc0) != 0x80)
00673 return (EOF);
00674
00675 ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
00676
00677 if (buf->current >= buf->end)
00678 if (mxml_fd_read(buf) < 0)
00679 return (EOF);
00680
00681 temp = *(buf->current)++;
00682
00683 if ((temp & 0xc0) != 0x80)
00684 return (EOF);
00685
00686 ch = (ch << 6) | (temp & 0x3f);
00687
00688 if (ch < 0x800)
00689 return (EOF);
00690 }
00691 else if ((ch & 0xf8) == 0xf0)
00692 {
00693
00694
00695
00696
00697 if (buf->current >= buf->end)
00698 if (mxml_fd_read(buf) < 0)
00699 return (EOF);
00700
00701 temp = *(buf->current)++;
00702
00703 if ((temp & 0xc0) != 0x80)
00704 return (EOF);
00705
00706 ch = ((ch & 0x07) << 6) | (temp & 0x3f);
00707
00708 if (buf->current >= buf->end)
00709 if (mxml_fd_read(buf) < 0)
00710 return (EOF);
00711
00712 temp = *(buf->current)++;
00713
00714 if ((temp & 0xc0) != 0x80)
00715 return (EOF);
00716
00717 ch = (ch << 6) | (temp & 0x3f);
00718
00719 if (buf->current >= buf->end)
00720 if (mxml_fd_read(buf) < 0)
00721 return (EOF);
00722
00723 temp = *(buf->current)++;
00724
00725 if ((temp & 0xc0) != 0x80)
00726 return (EOF);
00727
00728 ch = (ch << 6) | (temp & 0x3f);
00729
00730 if (ch < 0x10000)
00731 return (EOF);
00732 }
00733 else
00734 return (EOF);
00735 break;
00736
00737 case ENCODE_UTF16BE :
00738
00739
00740
00741
00742 if (buf->current >= buf->end)
00743 if (mxml_fd_read(buf) < 0)
00744 return (EOF);
00745
00746 temp = *(buf->current)++;
00747
00748 ch = (ch << 8) | temp;
00749
00750 if (mxml_bad_char(ch))
00751 {
00752 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00753 ch);
00754 return (EOF);
00755 }
00756 else if (ch >= 0xd800 && ch <= 0xdbff)
00757 {
00758
00759
00760
00761
00762 int lch;
00763
00764 if (buf->current >= buf->end)
00765 if (mxml_fd_read(buf) < 0)
00766 return (EOF);
00767
00768 lch = *(buf->current)++;
00769
00770 if (buf->current >= buf->end)
00771 if (mxml_fd_read(buf) < 0)
00772 return (EOF);
00773
00774 temp = *(buf->current)++;
00775
00776 lch = (lch << 8) | temp;
00777
00778 if (lch < 0xdc00 || lch >= 0xdfff)
00779 return (EOF);
00780
00781 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
00782 }
00783 break;
00784
00785 case ENCODE_UTF16LE :
00786
00787
00788
00789
00790 if (buf->current >= buf->end)
00791 if (mxml_fd_read(buf) < 0)
00792 return (EOF);
00793
00794 temp = *(buf->current)++;
00795
00796 ch |= (temp << 8);
00797
00798 if (mxml_bad_char(ch))
00799 {
00800 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00801 ch);
00802 return (EOF);
00803 }
00804 else if (ch >= 0xd800 && ch <= 0xdbff)
00805 {
00806
00807
00808
00809
00810 int lch;
00811
00812 if (buf->current >= buf->end)
00813 if (mxml_fd_read(buf) < 0)
00814 return (EOF);
00815
00816 lch = *(buf->current)++;
00817
00818 if (buf->current >= buf->end)
00819 if (mxml_fd_read(buf) < 0)
00820 return (EOF);
00821
00822 temp = *(buf->current)++;
00823
00824 lch |= (temp << 8);
00825
00826 if (lch < 0xdc00 || lch >= 0xdfff)
00827 return (EOF);
00828
00829 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
00830 }
00831 break;
00832 }
00833
00834 #if DEBUG > 1
00835 printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
00836 #endif
00837
00838 return (ch);
00839 }
00840
00841
00842
00843
00844
00845
00846 static int
00847 mxml_fd_putc(int ch,
00848 void *p)
00849 {
00850 mxml_fdbuf_t *buf;
00851
00852
00853
00854
00855
00856
00857
00858 buf = (mxml_fdbuf_t *)p;
00859
00860 if (buf->current >= buf->end)
00861 if (mxml_fd_write(buf) < 0)
00862 return (-1);
00863
00864 if (ch < 0x80)
00865 {
00866
00867
00868
00869
00870 *(buf->current)++ = ch;
00871 }
00872 else if (ch < 0x800)
00873 {
00874
00875
00876
00877
00878 *(buf->current)++ = 0xc0 | (ch >> 6);
00879 *(buf->current)++ = 0x80 | (ch & 0x3f);
00880 }
00881 else if (ch < 0x10000)
00882 {
00883
00884
00885
00886
00887 *(buf->current)++ = 0xe0 | (ch >> 12);
00888 *(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
00889 *(buf->current)++ = 0x80 | (ch & 0x3f);
00890 }
00891 else
00892 {
00893
00894
00895
00896
00897 *(buf->current)++ = 0xf0 | (ch >> 18);
00898 *(buf->current)++ = 0x80 | ((ch >> 12) & 0x3f);
00899 *(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
00900 *(buf->current)++ = 0x80 | (ch & 0x3f);
00901 }
00902
00903
00904
00905
00906
00907 return (0);
00908 }
00909
00910
00911
00912
00913
00914
00915 static int
00916 mxml_fd_read(mxml_fdbuf_t *buf)
00917 {
00918 int bytes;
00919
00920
00921
00922
00923
00924
00925 if (!buf)
00926 return (-1);
00927
00928
00929
00930
00931
00932 while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
00933 if (errno != EAGAIN && errno != EINTR)
00934 return (-1);
00935
00936 if (bytes == 0)
00937 return (-1);
00938
00939
00940
00941
00942
00943 buf->current = buf->buffer;
00944 buf->end = buf->buffer + bytes;
00945
00946 return (0);
00947 }
00948
00949
00950
00951
00952
00953
00954 static int
00955 mxml_fd_write(mxml_fdbuf_t *buf)
00956 {
00957 int bytes;
00958 unsigned char *ptr;
00959
00960
00961
00962
00963
00964
00965 if (!buf)
00966 return (-1);
00967
00968
00969
00970
00971
00972 if (buf->current == buf->buffer)
00973 return (0);
00974
00975
00976
00977
00978
00979 for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
00980 if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
00981 return (-1);
00982
00983
00984
00985
00986
00987 buf->current = buf->buffer;
00988
00989 return (0);
00990 }
00991
00992
00993
00994
00995
00996
00997 static int
00998 mxml_file_getc(void *p,
00999 int *encoding)
01000 {
01001 int ch,
01002 temp;
01003 FILE *fp;
01004
01005
01006
01007
01008
01009
01010 fp = (FILE *)p;
01011 ch = getc(fp);
01012
01013 if (ch == EOF)
01014 return (EOF);
01015
01016 switch (*encoding)
01017 {
01018 case ENCODE_UTF8 :
01019
01020
01021
01022
01023 if (!(ch & 0x80))
01024 {
01025 if (mxml_bad_char(ch))
01026 {
01027 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01028 ch);
01029 return (EOF);
01030 }
01031
01032 #if DEBUG > 1
01033 printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
01034 #endif
01035
01036 return (ch);
01037 }
01038 else if (ch == 0xfe)
01039 {
01040
01041
01042
01043
01044 ch = getc(fp);
01045 if (ch != 0xff)
01046 return (EOF);
01047
01048 *encoding = ENCODE_UTF16BE;
01049
01050 return (mxml_file_getc(p, encoding));
01051 }
01052 else if (ch == 0xff)
01053 {
01054
01055
01056
01057
01058 ch = getc(fp);
01059 if (ch != 0xfe)
01060 return (EOF);
01061
01062 *encoding = ENCODE_UTF16LE;
01063
01064 return (mxml_file_getc(p, encoding));
01065 }
01066 else if ((ch & 0xe0) == 0xc0)
01067 {
01068
01069
01070
01071
01072 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01073 return (EOF);
01074
01075 ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
01076
01077 if (ch < 0x80)
01078 return (EOF);
01079 }
01080 else if ((ch & 0xf0) == 0xe0)
01081 {
01082
01083
01084
01085
01086 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01087 return (EOF);
01088
01089 ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
01090
01091 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01092 return (EOF);
01093
01094 ch = (ch << 6) | (temp & 0x3f);
01095
01096 if (ch < 0x800)
01097 return (EOF);
01098 }
01099 else if ((ch & 0xf8) == 0xf0)
01100 {
01101
01102
01103
01104
01105 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01106 return (EOF);
01107
01108 ch = ((ch & 0x07) << 6) | (temp & 0x3f);
01109
01110 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01111 return (EOF);
01112
01113 ch = (ch << 6) | (temp & 0x3f);
01114
01115 if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01116 return (EOF);
01117
01118 ch = (ch << 6) | (temp & 0x3f);
01119
01120 if (ch < 0x10000)
01121 return (EOF);
01122 }
01123 else
01124 return (EOF);
01125 break;
01126
01127 case ENCODE_UTF16BE :
01128
01129
01130
01131
01132 ch = (ch << 8) | getc(fp);
01133
01134 if (mxml_bad_char(ch))
01135 {
01136 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01137 ch);
01138 return (EOF);
01139 }
01140 else if (ch >= 0xd800 && ch <= 0xdbff)
01141 {
01142
01143
01144
01145
01146 int lch = (getc(fp) << 8) | getc(fp);
01147
01148 if (lch < 0xdc00 || lch >= 0xdfff)
01149 return (EOF);
01150
01151 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
01152 }
01153 break;
01154
01155 case ENCODE_UTF16LE :
01156
01157
01158
01159
01160 ch |= (getc(fp) << 8);
01161
01162 if (mxml_bad_char(ch))
01163 {
01164 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01165 ch);
01166 return (EOF);
01167 }
01168 else if (ch >= 0xd800 && ch <= 0xdbff)
01169 {
01170
01171
01172
01173
01174 int lch = getc(fp) | (getc(fp) << 8);
01175
01176 if (lch < 0xdc00 || lch >= 0xdfff)
01177 return (EOF);
01178
01179 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
01180 }
01181 break;
01182 }
01183
01184 #if DEBUG > 1
01185 printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
01186 #endif
01187
01188 return (ch);
01189 }
01190
01191
01192
01193
01194
01195
01196 static int
01197 mxml_file_putc(int ch,
01198 void *p)
01199 {
01200 char buffer[4],
01201 *bufptr;
01202 int buflen;
01203
01204
01205 if (ch < 0x80)
01206 return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
01207
01208 bufptr = buffer;
01209
01210 if (ch < 0x800)
01211 {
01212
01213
01214
01215
01216 *bufptr++ = 0xc0 | (ch >> 6);
01217 *bufptr++ = 0x80 | (ch & 0x3f);
01218 }
01219 else if (ch < 0x10000)
01220 {
01221
01222
01223
01224
01225 *bufptr++ = 0xe0 | (ch >> 12);
01226 *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
01227 *bufptr++ = 0x80 | (ch & 0x3f);
01228 }
01229 else
01230 {
01231
01232
01233
01234
01235 *bufptr++ = 0xf0 | (ch >> 18);
01236 *bufptr++ = 0x80 | ((ch >> 12) & 0x3f);
01237 *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
01238 *bufptr++ = 0x80 | (ch & 0x3f);
01239 }
01240
01241 buflen = bufptr - buffer;
01242
01243 return (fwrite(buffer, 1, buflen, (FILE *)p) < buflen ? -1 : 0);
01244 }
01245
01246
01247
01248
01249
01250
01251 static int
01252 mxml_get_entity(mxml_node_t *parent,
01253 void *p,
01254 int *encoding,
01255 int (*getc_cb)(void *, int *))
01256
01257 {
01258 int ch;
01259 char entity[64],
01260 *entptr;
01261
01262
01263 entptr = entity;
01264
01265 while ((ch = (*getc_cb)(p, encoding)) != EOF)
01266 if (ch > 126 || (!isalnum(ch) && ch != '#'))
01267 break;
01268 else if (entptr < (entity + sizeof(entity) - 1))
01269 *entptr++ = ch;
01270 else
01271 {
01272 mxml_error("Entity name too long under parent <%s>!",
01273 parent ? parent->value.element.name : "null");
01274 break;
01275 }
01276
01277 *entptr = '\0';
01278
01279 if (ch != ';')
01280 {
01281 mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
01282 entity, parent ? parent->value.element.name : "null");
01283 return (EOF);
01284 }
01285
01286 if (entity[0] == '#')
01287 {
01288 if (entity[1] == 'x')
01289 ch = strtol(entity + 2, NULL, 16);
01290 else
01291 ch = strtol(entity + 1, NULL, 10);
01292 }
01293 else if ((ch = mxmlEntityGetValue(entity)) < 0)
01294 mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
01295 entity, parent ? parent->value.element.name : "null");
01296
01297 if (mxml_bad_char(ch))
01298 {
01299 mxml_error("Bad control character 0x%02x under parent <%s> not allowed by XML standard!",
01300 ch, parent ? parent->value.element.name : "null");
01301 return (EOF);
01302 }
01303
01304 return (ch);
01305 }
01306
01307
01308
01309
01310
01311
01312 static mxml_node_t *
01313 mxml_load_data(mxml_node_t *top,
01314 void *p,
01315 mxml_type_t (*cb)(mxml_node_t *),
01316
01317 int (*getc_cb)(void *, int *))
01318
01319 {
01320 mxml_node_t *node,
01321 *first,
01322 *parent;
01323 int ch,
01324 whitespace;
01325 char *buffer,
01326 *bufptr;
01327 int bufsize;
01328 mxml_type_t type;
01329 int encoding;
01330 static const char * const types[] =
01331 {
01332 "MXML_ELEMENT",
01333 "MXML_INTEGER",
01334 "MXML_OPAQUE",
01335 "MXML_REAL",
01336 "MXML_TEXT",
01337 "MXML_CUSTOM"
01338 };
01339
01340
01341
01342
01343
01344
01345 if ((buffer = malloc(64)) == NULL)
01346 {
01347 mxml_error("Unable to allocate string buffer!");
01348 return (NULL);
01349 }
01350
01351 bufsize = 64;
01352 bufptr = buffer;
01353 parent = top;
01354 first = NULL;
01355 whitespace = 0;
01356 encoding = ENCODE_UTF8;
01357
01358 if (cb && parent)
01359 type = (*cb)(parent);
01360 else
01361 type = MXML_TEXT;
01362
01363 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01364 {
01365 if ((ch == '<' ||
01366 (isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&
01367 bufptr > buffer)
01368 {
01369
01370
01371
01372
01373 *bufptr = '\0';
01374
01375 switch (type)
01376 {
01377 case MXML_INTEGER :
01378 node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
01379 break;
01380
01381 case MXML_OPAQUE :
01382 node = mxmlNewOpaque(parent, buffer);
01383 break;
01384
01385 case MXML_REAL :
01386 node = mxmlNewReal(parent, strtod(buffer, &bufptr));
01387 break;
01388
01389 case MXML_TEXT :
01390 node = mxmlNewText(parent, whitespace, buffer);
01391 break;
01392
01393 case MXML_CUSTOM :
01394 if (mxml_custom_load_cb)
01395 {
01396
01397
01398
01399
01400 node = mxmlNewCustom(parent, NULL, NULL);
01401
01402 if ((*mxml_custom_load_cb)(node, buffer))
01403 {
01404 mxml_error("Bad custom value '%s' in parent <%s>!",
01405 buffer, parent ? parent->value.element.name : "null");
01406 mxmlDelete(node);
01407 node = NULL;
01408 }
01409 break;
01410 }
01411
01412 default :
01413 node = NULL;
01414 break;
01415 }
01416
01417 if (*bufptr)
01418 {
01419
01420
01421
01422
01423 mxml_error("Bad %s value '%s' in parent <%s>!",
01424 type == MXML_INTEGER ? "integer" : "real", buffer,
01425 parent ? parent->value.element.name : "null");
01426 break;
01427 }
01428
01429 bufptr = buffer;
01430 whitespace = isspace(ch) && type == MXML_TEXT;
01431
01432 if (!node)
01433 {
01434
01435
01436
01437
01438 mxml_error("Unable to add value node of type %s to parent <%s>!",
01439 types[type], parent ? parent->value.element.name : "null");
01440 goto error;
01441 }
01442
01443 if (!first)
01444 first = node;
01445 }
01446 else if (isspace(ch) && type == MXML_TEXT)
01447 whitespace = 1;
01448
01449
01450
01451
01452
01453
01454 if (ch == '<' && whitespace && type == MXML_TEXT)
01455 {
01456 mxmlNewText(parent, whitespace, "");
01457 whitespace = 0;
01458 }
01459
01460 if (ch == '<')
01461 {
01462
01463
01464
01465
01466 bufptr = buffer;
01467
01468 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01469 if (isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
01470 break;
01471 else if (ch == '&')
01472 {
01473 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01474 goto error;
01475
01476 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01477 goto error;
01478 }
01479 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01480 goto error;
01481 else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||
01482 ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||
01483 ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))
01484 break;
01485
01486 *bufptr = '\0';
01487
01488 if (!strcmp(buffer, "!--"))
01489 {
01490
01491
01492
01493
01494 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01495 {
01496 if (ch == '>' && bufptr > (buffer + 4) &&
01497 bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')
01498 break;
01499 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01500 goto error;
01501 }
01502
01503
01504
01505
01506
01507 if (ch != '>')
01508 {
01509
01510
01511
01512
01513 mxml_error("Early EOF in comment node!");
01514 goto error;
01515 }
01516
01517
01518
01519
01520
01521
01522 *bufptr = '\0';
01523
01524 if (!mxmlNewElement(parent, buffer))
01525 {
01526
01527
01528
01529
01530 mxml_error("Unable to add comment node to parent <%s>!",
01531 parent ? parent->value.element.name : "null");
01532 break;
01533 }
01534 }
01535 else if (!strcmp(buffer, "![CDATA["))
01536 {
01537
01538
01539
01540
01541 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01542 {
01543 if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))
01544 break;
01545 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01546 goto error;
01547 }
01548
01549
01550
01551
01552
01553 if (ch != '>')
01554 {
01555
01556
01557
01558
01559 mxml_error("Early EOF in CDATA node!");
01560 goto error;
01561 }
01562
01563
01564
01565
01566
01567
01568 *bufptr = '\0';
01569
01570 if (!mxmlNewElement(parent, buffer))
01571 {
01572
01573
01574
01575
01576 mxml_error("Unable to add CDATA node to parent <%s>!",
01577 parent ? parent->value.element.name : "null");
01578 goto error;
01579 }
01580 }
01581 else if (buffer[0] == '?')
01582 {
01583
01584
01585
01586
01587 while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01588 {
01589 if (ch == '>' && bufptr > buffer && bufptr[-1] == '?')
01590 break;
01591 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01592 goto error;
01593 }
01594
01595
01596
01597
01598
01599 if (ch != '>')
01600 {
01601
01602
01603
01604
01605 mxml_error("Early EOF in processing instruction node!");
01606 goto error;
01607 }
01608
01609
01610
01611
01612
01613
01614 *bufptr = '\0';
01615
01616 if (!(parent = mxmlNewElement(parent, buffer)))
01617 {
01618
01619
01620
01621
01622 mxml_error("Unable to add processing instruction node to parent <%s>!",
01623 parent ? parent->value.element.name : "null");
01624 goto error;
01625 }
01626
01627 if (cb)
01628 type = (*cb)(parent);
01629 }
01630 else if (buffer[0] == '!')
01631 {
01632
01633
01634
01635
01636 do
01637 {
01638 if (ch == '>')
01639 break;
01640 else
01641 {
01642 if (ch == '&')
01643 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01644 goto error;
01645
01646 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01647 goto error;
01648 }
01649 }
01650 while ((ch = (*getc_cb)(p, &encoding)) != EOF);
01651
01652
01653
01654
01655
01656 if (ch != '>')
01657 {
01658
01659
01660
01661
01662 mxml_error("Early EOF in declaration node!");
01663 goto error;
01664 }
01665
01666
01667
01668
01669
01670 *bufptr = '\0';
01671
01672 node = mxmlNewElement(parent, buffer);
01673 if (!node)
01674 {
01675
01676
01677
01678
01679 mxml_error("Unable to add declaration node to parent <%s>!",
01680 parent ? parent->value.element.name : "null");
01681 goto error;
01682 }
01683
01684
01685
01686
01687
01688 parent = node;
01689
01690 if (cb)
01691 type = (*cb)(parent);
01692 }
01693 else if (buffer[0] == '/')
01694 {
01695
01696
01697
01698
01699 if (!parent || strcmp(buffer + 1, parent->value.element.name))
01700 {
01701
01702
01703
01704
01705 mxml_error("Mismatched close tag <%s> under parent <%s>!",
01706 buffer, parent->value.element.name);
01707 goto error;
01708 }
01709
01710
01711
01712
01713
01714 while (ch != '>' && ch != EOF)
01715 ch = (*getc_cb)(p, &encoding);
01716
01717
01718
01719
01720
01721 parent = parent->parent;
01722
01723 if (cb && parent)
01724 type = (*cb)(parent);
01725 }
01726 else
01727 {
01728
01729
01730
01731
01732 node = mxmlNewElement(parent, buffer);
01733
01734 if (!node)
01735 {
01736
01737
01738
01739
01740 mxml_error("Unable to add element node to parent <%s>!",
01741 parent ? parent->value.element.name : "null");
01742 goto error;
01743 }
01744
01745 if (isspace(ch))
01746 ch = mxml_parse_element(node, p, &encoding, getc_cb);
01747 else if (ch == '/')
01748 {
01749 if ((ch = (*getc_cb)(p, &encoding)) != '>')
01750 {
01751 mxml_error("Expected > but got '%c' instead for element <%s/>!",
01752 ch, buffer);
01753 goto error;
01754 }
01755
01756 ch = '/';
01757 }
01758
01759 if (ch == EOF)
01760 break;
01761
01762 if (ch != '/')
01763 {
01764
01765
01766
01767
01768 parent = node;
01769
01770 if (cb && parent)
01771 type = (*cb)(parent);
01772 }
01773 }
01774
01775 bufptr = buffer;
01776 }
01777 else if (ch == '&')
01778 {
01779
01780
01781
01782
01783 if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01784 goto error;
01785
01786 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01787 goto error;
01788 }
01789 else if (type == MXML_OPAQUE || type == MXML_CUSTOM || !isspace(ch))
01790 {
01791
01792
01793
01794
01795 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01796 goto error;
01797 }
01798 }
01799
01800
01801
01802
01803
01804 free(buffer);
01805
01806
01807
01808
01809
01810 if (parent)
01811 {
01812 while (parent->parent != top && parent->parent)
01813 parent = parent->parent;
01814 }
01815
01816 return (parent);
01817
01818
01819
01820
01821
01822 error:
01823
01824 mxmlDelete(first);
01825
01826 free(buffer);
01827
01828 return (NULL);
01829 }
01830
01831
01832
01833
01834
01835
01836 static int
01837 mxml_parse_element(mxml_node_t *node,
01838 void *p,
01839 int *encoding,
01840
01841 int (*getc_cb)(void *, int *))
01842
01843 {
01844 int ch,
01845 quote;
01846 char *name,
01847 *value,
01848 *ptr;
01849 int namesize,
01850 valsize;
01851
01852
01853
01854
01855
01856
01857
01858
01859 if ((name = malloc(64)) == NULL)
01860 {
01861 mxml_error("Unable to allocate memory for name!");
01862 return (EOF);
01863 }
01864
01865 namesize = 64;
01866
01867 if ((value = malloc(64)) == NULL)
01868 {
01869 free(name);
01870 mxml_error("Unable to allocate memory for value!");
01871 return (EOF);
01872 }
01873
01874 valsize = 64;
01875
01876
01877
01878
01879
01880 while ((ch = (*getc_cb)(p, encoding)) != EOF)
01881 {
01882 #if DEBUG > 1
01883 fprintf(stderr, "parse_element: ch='%c'\n", ch);
01884 #endif
01885
01886
01887
01888
01889
01890 if (isspace(ch))
01891 continue;
01892
01893
01894
01895
01896
01897 if (ch == '/' || ch == '?')
01898 {
01899
01900
01901
01902
01903 quote = (*getc_cb)(p, encoding);
01904
01905 if (quote != '>')
01906 {
01907 mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
01908 ch, node->value.element.name, quote);
01909 ch = EOF;
01910 }
01911
01912 break;
01913 }
01914 else if (ch == '>')
01915 break;
01916
01917
01918
01919
01920
01921 name[0] = ch;
01922 ptr = name + 1;
01923
01924 if (ch == '\"' || ch == '\'')
01925 {
01926
01927
01928
01929
01930 quote = ch;
01931
01932 while ((ch = (*getc_cb)(p, encoding)) != EOF)
01933 {
01934 if (ch == '&')
01935 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
01936 goto error;
01937
01938 if (mxml_add_char(ch, &ptr, &name, &namesize))
01939 goto error;
01940
01941 if (ch == quote)
01942 break;
01943 }
01944 }
01945 else
01946 {
01947
01948
01949
01950
01951 while ((ch = (*getc_cb)(p, encoding)) != EOF)
01952 if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
01953 break;
01954 else
01955 {
01956 if (ch == '&')
01957 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
01958 goto error;
01959
01960 if (mxml_add_char(ch, &ptr, &name, &namesize))
01961 goto error;
01962 }
01963 }
01964
01965 *ptr = '\0';
01966
01967 if (mxmlElementGetAttr(node, name))
01968 goto error;
01969
01970 if (ch == '=')
01971 {
01972
01973
01974
01975
01976 if ((ch = (*getc_cb)(p, encoding)) == EOF)
01977 {
01978 mxml_error("Missing value for attribute '%s' in element %s!",
01979 name, node->value.element.name);
01980 return (EOF);
01981 }
01982
01983 if (ch == '\'' || ch == '\"')
01984 {
01985
01986
01987
01988
01989 quote = ch;
01990 ptr = value;
01991
01992 while ((ch = (*getc_cb)(p, encoding)) != EOF)
01993 if (ch == quote)
01994 break;
01995 else
01996 {
01997 if (ch == '&')
01998 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
01999 goto error;
02000
02001 if (mxml_add_char(ch, &ptr, &value, &valsize))
02002 goto error;
02003 }
02004
02005 *ptr = '\0';
02006 }
02007 else
02008 {
02009
02010
02011
02012
02013 value[0] = ch;
02014 ptr = value + 1;
02015
02016 while ((ch = (*getc_cb)(p, encoding)) != EOF)
02017 if (isspace(ch) || ch == '=' || ch == '/' || ch == '>')
02018 break;
02019 else
02020 {
02021 if (ch == '&')
02022 if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
02023 goto error;
02024
02025 if (mxml_add_char(ch, &ptr, &value, &valsize))
02026 goto error;
02027 }
02028
02029 *ptr = '\0';
02030 }
02031
02032
02033
02034
02035
02036 mxmlElementSetAttr(node, name, value);
02037 }
02038 else
02039 {
02040
02041
02042
02043
02044 mxmlElementSetAttr(node, name, NULL);
02045 }
02046
02047
02048
02049
02050
02051 if (ch == '/' || ch == '?')
02052 {
02053
02054
02055
02056
02057 quote = (*getc_cb)(p, encoding);
02058
02059 if (quote != '>')
02060 {
02061 mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
02062 ch, node->value.element.name, quote);
02063 ch = EOF;
02064 }
02065
02066 break;
02067 }
02068 else if (ch == '>')
02069 break;
02070 }
02071
02072
02073
02074
02075
02076 free(name);
02077 free(value);
02078
02079 return (ch);
02080
02081
02082
02083
02084
02085 error:
02086
02087 free(name);
02088 free(value);
02089
02090 return (EOF);
02091 }
02092
02093
02094
02095
02096
02097
02098 static int
02099 mxml_string_getc(void *p,
02100 int *encoding)
02101 {
02102 int ch;
02103 const char **s;
02104
02105
02106 s = (const char **)p;
02107
02108 if ((ch = (*s)[0] & 255) != 0 || *encoding == ENCODE_UTF16LE)
02109 {
02110
02111
02112
02113
02114 (*s)++;
02115
02116 switch (*encoding)
02117 {
02118 case ENCODE_UTF8 :
02119 if (!(ch & 0x80))
02120 {
02121 #if DEBUG > 1
02122 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02123 #endif
02124
02125 if (mxml_bad_char(ch))
02126 {
02127 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02128 ch);
02129 return (EOF);
02130 }
02131
02132 return (ch);
02133 }
02134 else if (ch == 0xfe)
02135 {
02136
02137
02138
02139
02140 if (((*s)[0] & 255) != 0xff)
02141 return (EOF);
02142
02143 *encoding = ENCODE_UTF16BE;
02144 (*s)++;
02145
02146 return (mxml_string_getc(p, encoding));
02147 }
02148 else if (ch == 0xff)
02149 {
02150
02151
02152
02153
02154 if (((*s)[0] & 255) != 0xfe)
02155 return (EOF);
02156
02157 *encoding = ENCODE_UTF16LE;
02158 (*s)++;
02159
02160 return (mxml_string_getc(p, encoding));
02161 }
02162 else if ((ch & 0xe0) == 0xc0)
02163 {
02164
02165
02166
02167
02168 if (((*s)[0] & 0xc0) != 0x80)
02169 return (EOF);
02170
02171 ch = ((ch & 0x1f) << 6) | ((*s)[0] & 0x3f);
02172
02173 (*s)++;
02174
02175 if (ch < 0x80)
02176 return (EOF);
02177
02178 #if DEBUG > 1
02179 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02180 #endif
02181
02182 return (ch);
02183 }
02184 else if ((ch & 0xf0) == 0xe0)
02185 {
02186
02187
02188
02189
02190 if (((*s)[0] & 0xc0) != 0x80 ||
02191 ((*s)[1] & 0xc0) != 0x80)
02192 return (EOF);
02193
02194 ch = ((((ch & 0x0f) << 6) | ((*s)[0] & 0x3f)) << 6) | ((*s)[1] & 0x3f);
02195
02196 (*s) += 2;
02197
02198 if (ch < 0x800)
02199 return (EOF);
02200
02201 #if DEBUG > 1
02202 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02203 #endif
02204
02205 return (ch);
02206 }
02207 else if ((ch & 0xf8) == 0xf0)
02208 {
02209
02210
02211
02212
02213 if (((*s)[0] & 0xc0) != 0x80 ||
02214 ((*s)[1] & 0xc0) != 0x80 ||
02215 ((*s)[2] & 0xc0) != 0x80)
02216 return (EOF);
02217
02218 ch = ((((((ch & 0x07) << 6) | ((*s)[0] & 0x3f)) << 6) |
02219 ((*s)[1] & 0x3f)) << 6) | ((*s)[2] & 0x3f);
02220
02221 (*s) += 3;
02222
02223 if (ch < 0x10000)
02224 return (EOF);
02225
02226 #if DEBUG > 1
02227 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02228 #endif
02229
02230 return (ch);
02231 }
02232 else
02233 return (EOF);
02234
02235 case ENCODE_UTF16BE :
02236
02237
02238
02239
02240 ch = (ch << 8) | ((*s)[0] & 255);
02241 (*s) ++;
02242
02243 if (mxml_bad_char(ch))
02244 {
02245 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02246 ch);
02247 return (EOF);
02248 }
02249 else if (ch >= 0xd800 && ch <= 0xdbff)
02250 {
02251
02252
02253
02254
02255 int lch;
02256
02257
02258 if (!(*s)[0])
02259 return (EOF);
02260
02261 lch = (((*s)[0] & 255) << 8) | ((*s)[1] & 255);
02262 (*s) += 2;
02263
02264 if (lch < 0xdc00 || lch >= 0xdfff)
02265 return (EOF);
02266
02267 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
02268 }
02269
02270 #if DEBUG > 1
02271 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02272 #endif
02273
02274 return (ch);
02275
02276 case ENCODE_UTF16LE :
02277
02278
02279
02280
02281 ch = ch | (((*s)[0] & 255) << 8);
02282
02283 if (!ch)
02284 {
02285 (*s) --;
02286 return (EOF);
02287 }
02288
02289 (*s) ++;
02290
02291 if (mxml_bad_char(ch))
02292 {
02293 mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02294 ch);
02295 return (EOF);
02296 }
02297 else if (ch >= 0xd800 && ch <= 0xdbff)
02298 {
02299
02300
02301
02302
02303 int lch;
02304
02305
02306 if (!(*s)[1])
02307 return (EOF);
02308
02309 lch = (((*s)[1] & 255) << 8) | ((*s)[0] & 255);
02310 (*s) += 2;
02311
02312 if (lch < 0xdc00 || lch >= 0xdfff)
02313 return (EOF);
02314
02315 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
02316 }
02317
02318 #if DEBUG > 1
02319 printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02320 #endif
02321
02322 return (ch);
02323 }
02324 }
02325
02326 return (EOF);
02327 }
02328
02329
02330
02331
02332
02333
02334 static int
02335 mxml_string_putc(int ch,
02336 void *p)
02337 {
02338 char **pp;
02339
02340
02341 pp = (char **)p;
02342
02343 if (ch < 0x80)
02344 {
02345
02346
02347
02348
02349 if (pp[0] < pp[1])
02350 pp[0][0] = ch;
02351
02352 pp[0] ++;
02353 }
02354 else if (ch < 0x800)
02355 {
02356
02357
02358
02359
02360 if ((pp[0] + 1) < pp[1])
02361 {
02362 pp[0][0] = 0xc0 | (ch >> 6);
02363 pp[0][1] = 0x80 | (ch & 0x3f);
02364 }
02365
02366 pp[0] += 2;
02367 }
02368 else if (ch < 0x10000)
02369 {
02370
02371
02372
02373
02374 if ((pp[0] + 2) < pp[1])
02375 {
02376 pp[0][0] = 0xe0 | (ch >> 12);
02377 pp[0][1] = 0x80 | ((ch >> 6) & 0x3f);
02378 pp[0][2] = 0x80 | (ch & 0x3f);
02379 }
02380
02381 pp[0] += 3;
02382 }
02383 else
02384 {
02385
02386
02387
02388
02389 if ((pp[0] + 2) < pp[1])
02390 {
02391 pp[0][0] = 0xf0 | (ch >> 18);
02392 pp[0][1] = 0x80 | ((ch >> 12) & 0x3f);
02393 pp[0][2] = 0x80 | ((ch >> 6) & 0x3f);
02394 pp[0][3] = 0x80 | (ch & 0x3f);
02395 }
02396
02397 pp[0] += 4;
02398 }
02399
02400 return (0);
02401 }
02402
02403
02404
02405
02406
02407
02408 static int
02409 mxml_write_name(const char *s,
02410 void *p,
02411 int (*putc_cb)(int, void *))
02412
02413 {
02414 char quote;
02415 const char *name;
02416
02417
02418 if (*s == '\"' || *s == '\'')
02419 {
02420
02421
02422
02423
02424 if ((*putc_cb)(*s, p) < 0)
02425 return (-1);
02426
02427 quote = *s++;
02428
02429 while (*s && *s != quote)
02430 {
02431 if ((name = mxmlEntityGetName(*s)) != NULL)
02432 {
02433 if ((*putc_cb)('&', p) < 0)
02434 return (-1);
02435
02436 while (*name)
02437 {
02438 if ((*putc_cb)(*name, p) < 0)
02439 return (-1);
02440
02441 name ++;
02442 }
02443
02444 if ((*putc_cb)(';', p) < 0)
02445 return (-1);
02446 }
02447 else if ((*putc_cb)(*s, p) < 0)
02448 return (-1);
02449
02450 s ++;
02451 }
02452
02453
02454
02455
02456
02457 if ((*putc_cb)(quote, p) < 0)
02458 return (-1);
02459 }
02460 else
02461 {
02462
02463
02464
02465
02466 while (*s)
02467 {
02468 if ((*putc_cb)(*s, p) < 0)
02469 return (-1);
02470
02471 s ++;
02472 }
02473 }
02474
02475 return (0);
02476 }
02477
02478
02479
02480
02481
02482
02483 static int
02484 mxml_write_node(mxml_node_t *node,
02485 void *p,
02486 const char *(*cb)(mxml_node_t *, int),
02487
02488 int col,
02489 int (*putc_cb)(int, void *))
02490 {
02491 int i,
02492 width;
02493 mxml_attr_t *attr;
02494 char s[255];
02495
02496
02497 while (node != NULL)
02498 {
02499
02500
02501
02502
02503 switch (node->type)
02504 {
02505 case MXML_ELEMENT :
02506 col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
02507
02508 if ((*putc_cb)('<', p) < 0)
02509 return (-1);
02510 if (node->value.element.name[0] == '?' ||
02511 !strncmp(node->value.element.name, "!--", 3) ||
02512 !strncmp(node->value.element.name, "![CDATA[", 8))
02513 {
02514
02515
02516
02517
02518
02519 const char *ptr;
02520
02521
02522 for (ptr = node->value.element.name; *ptr; ptr ++)
02523 if ((*putc_cb)(*ptr, p) < 0)
02524 return (-1);
02525
02526
02527
02528
02529
02530 if (!strncmp(node->value.element.name, "?xml", 4))
02531 col = MXML_WRAP;
02532 }
02533 else if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
02534 return (-1);
02535
02536 col += strlen(node->value.element.name) + 1;
02537
02538 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
02539 i > 0;
02540 i --, attr ++)
02541 {
02542 width = strlen(attr->name);
02543
02544 if (attr->value)
02545 width += strlen(attr->value) + 3;
02546
02547 if ((col + width) > MXML_WRAP)
02548 {
02549 if ((*putc_cb)('\n', p) < 0)
02550 return (-1);
02551
02552 col = 0;
02553 }
02554 else
02555 {
02556 if ((*putc_cb)(' ', p) < 0)
02557 return (-1);
02558
02559 col ++;
02560 }
02561
02562 if (mxml_write_name(attr->name, p, putc_cb) < 0)
02563 return (-1);
02564
02565 if (attr->value)
02566 {
02567 if ((*putc_cb)('=', p) < 0)
02568 return (-1);
02569 if ((*putc_cb)('\"', p) < 0)
02570 return (-1);
02571 if (mxml_write_string(attr->value, p, putc_cb) < 0)
02572 return (-1);
02573 if ((*putc_cb)('\"', p) < 0)
02574 return (-1);
02575 }
02576
02577 col += width;
02578 }
02579
02580 if (node->child)
02581 {
02582
02583
02584
02585
02586 if ((*putc_cb)('>', p) < 0)
02587 return (-1);
02588 else
02589 col ++;
02590
02591 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02592
02593 if ((col = mxml_write_node(node->child, p, cb, col, putc_cb)) < 0)
02594 return (-1);
02595
02596
02597
02598
02599
02600 if (node->value.element.name[0] != '!' &&
02601 node->value.element.name[0] != '?')
02602 {
02603 col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_CLOSE, col, putc_cb);
02604
02605 if ((*putc_cb)('<', p) < 0)
02606 return (-1);
02607 if ((*putc_cb)('/', p) < 0)
02608 return (-1);
02609 if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
02610 return (-1);
02611 if ((*putc_cb)('>', p) < 0)
02612 return (-1);
02613
02614 col += strlen(node->value.element.name) + 3;
02615
02616 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
02617 }
02618 }
02619 else if (node->value.element.name[0] == '!' ||
02620 node->value.element.name[0] == '?')
02621 {
02622
02623
02624
02625
02626 if ((*putc_cb)('>', p) < 0)
02627 return (-1);
02628 else
02629 col ++;
02630
02631 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02632 }
02633 else
02634 {
02635 if ((*putc_cb)(' ', p) < 0)
02636 return (-1);
02637 if ((*putc_cb)('/', p) < 0)
02638 return (-1);
02639 if ((*putc_cb)('>', p) < 0)
02640 return (-1);
02641
02642 col += 3;
02643
02644 col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02645 }
02646 break;
02647
02648 case MXML_INTEGER :
02649 if (node->prev)
02650 {
02651 if (col > MXML_WRAP)
02652 {
02653 if ((*putc_cb)('\n', p) < 0)
02654 return (-1);
02655
02656 col = 0;
02657 }
02658 else if ((*putc_cb)(' ', p) < 0)
02659 return (-1);
02660 else
02661 col ++;
02662 }
02663
02664 sprintf(s, "%d", node->value.integer);
02665 if (mxml_write_string(s, p, putc_cb) < 0)
02666 return (-1);
02667
02668 col += strlen(s);
02669 break;
02670
02671 case MXML_OPAQUE :
02672 if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
02673 return (-1);
02674
02675 col += strlen(node->value.opaque);
02676 break;
02677
02678 case MXML_REAL :
02679 if (node->prev)
02680 {
02681 if (col > MXML_WRAP)
02682 {
02683 if ((*putc_cb)('\n', p) < 0)
02684 return (-1);
02685
02686 col = 0;
02687 }
02688 else if ((*putc_cb)(' ', p) < 0)
02689 return (-1);
02690 else
02691 col ++;
02692 }
02693
02694 sprintf(s, "%f", node->value.real);
02695 if (mxml_write_string(s, p, putc_cb) < 0)
02696 return (-1);
02697
02698 col += strlen(s);
02699 break;
02700
02701 case MXML_TEXT :
02702 if (node->value.text.whitespace && col > 0)
02703 {
02704 if (col > MXML_WRAP)
02705 {
02706 if ((*putc_cb)('\n', p) < 0)
02707 return (-1);
02708
02709 col = 0;
02710 }
02711 else if ((*putc_cb)(' ', p) < 0)
02712 return (-1);
02713 else
02714 col ++;
02715 }
02716
02717 if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
02718 return (-1);
02719
02720 col += strlen(node->value.text.string);
02721 break;
02722
02723 case MXML_CUSTOM :
02724 if (mxml_custom_save_cb)
02725 {
02726 char *data;
02727 const char *newline;
02728
02729
02730 if ((data = (*mxml_custom_save_cb)(node)) == NULL)
02731 return (-1);
02732
02733 if (mxml_write_string(data, p, putc_cb) < 0)
02734 return (-1);
02735
02736 if ((newline = strrchr(data, '\n')) == NULL)
02737 col += strlen(data);
02738 else
02739 col = strlen(newline);
02740
02741 free(data);
02742 break;
02743 }
02744
02745 default :
02746 return (-1);
02747 }
02748
02749
02750
02751
02752
02753 node = node->next;
02754 }
02755
02756 return (col);
02757 }
02758
02759
02760
02761
02762
02763
02764 static int
02765 mxml_write_string(const char *s,
02766 void *p,
02767 int (*putc_cb)(int, void *))
02768
02769 {
02770 const char *name;
02771
02772
02773 while (*s)
02774 {
02775 if ((name = mxmlEntityGetName(*s)) != NULL)
02776 {
02777 if ((*putc_cb)('&', p) < 0)
02778 return (-1);
02779
02780 while (*name)
02781 {
02782 if ((*putc_cb)(*name, p) < 0)
02783 return (-1);
02784 name ++;
02785 }
02786
02787 if ((*putc_cb)(';', p) < 0)
02788 return (-1);
02789 }
02790 else if ((*putc_cb)(*s, p) < 0)
02791 return (-1);
02792
02793 s ++;
02794 }
02795
02796 return (0);
02797 }
02798
02799
02800
02801
02802
02803
02804 static int
02805 mxml_write_ws(mxml_node_t *node,
02806 void *p,
02807 const char *(*cb)(mxml_node_t *, int),
02808
02809 int ws,
02810 int col,
02811 int (*putc_cb)(int, void *))
02812
02813 {
02814 const char *s;
02815
02816
02817 if (cb && (s = (*cb)(node, ws)) != NULL)
02818 {
02819 while (*s)
02820 {
02821 if ((*putc_cb)(*s, p) < 0)
02822 return (-1);
02823 else if (*s == '\n')
02824 col = 0;
02825 else if (*s == '\t')
02826 {
02827 col += MXML_TAB;
02828 col = col - (col % MXML_TAB);
02829 }
02830 else
02831 col ++;
02832
02833 s ++;
02834 }
02835 }
02836
02837 return (col);
02838 }
02839
02840
02841
02842
02843