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