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