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 #include <gimp-print/mxml.h>
00040 #include "config.h"
00041
00042
00043
00044
00045
00046
00047 static int mxml_add_char(int ch, char **ptr, char **buffer,
00048 int *bufsize);
00049 static int mxml_file_getc(void *p);
00050 static int mxml_file_putc(int ch, void *p);
00051 static stp_mxml_node_t *mxml_load_data(stp_mxml_node_t *top, void *p,
00052 stp_mxml_type_t (*cb)(stp_mxml_node_t *),
00053 int (*getc_cb)(void *));
00054 static int mxml_parse_element(stp_mxml_node_t *node, void *p,
00055 int (*getc_cb)(void *));
00056 static int mxml_string_getc(void *p);
00057 static int mxml_string_putc(int ch, void *p);
00058 static int mxml_write_node(stp_mxml_node_t *node, void *p,
00059 int (*cb)(stp_mxml_node_t *, int),
00060 int col,
00061 int (*putc_cb)(int, void *));
00062 static int mxml_write_string(const char *s, void *p,
00063 int (*putc_cb)(int, void *));
00064 static int mxml_write_ws(stp_mxml_node_t *node, void *p,
00065 int (*cb)(stp_mxml_node_t *, int), int ws,
00066 int col, int (*putc_cb)(int, void *));
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 stp_mxml_node_t *
00081 stp_mxmlLoadFile(stp_mxml_node_t *top,
00082 FILE *fp,
00083 stp_mxml_type_t (*cb)(stp_mxml_node_t *))
00084
00085 {
00086 return (mxml_load_data(top, fp, cb, mxml_file_getc));
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 stp_mxml_node_t *
00102 stp_mxmlLoadString(stp_mxml_node_t *top,
00103 const char *s,
00104 stp_mxml_type_t (*cb)(stp_mxml_node_t *))
00105
00106 {
00107 return (mxml_load_data(top, &s, cb, mxml_string_getc));
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 char *
00122 stp_mxmlSaveAllocString(stp_mxml_node_t *node,
00123 int (*cb)(stp_mxml_node_t *, int))
00124
00125 {
00126 int bytes;
00127 char buffer[8192];
00128 char *s;
00129
00130
00131
00132
00133
00134
00135 bytes = stp_mxmlSaveString(node, buffer, sizeof(buffer), cb);
00136
00137 if (bytes <= 0)
00138 return (NULL);
00139
00140 if (bytes < (int)(sizeof(buffer) - 1))
00141 {
00142
00143
00144
00145
00146
00147 return (strdup(buffer));
00148 }
00149
00150
00151
00152
00153
00154
00155 if ((s = malloc(bytes + 1)) == NULL)
00156 return (NULL);
00157
00158 stp_mxmlSaveString(node, s, bytes + 1, cb);
00159
00160
00161
00162
00163
00164 return (s);
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 int
00179 stp_mxmlSaveFile(stp_mxml_node_t *node,
00180 FILE *fp,
00181 int (*cb)(stp_mxml_node_t *, int))
00182
00183 {
00184 int col;
00185
00186
00187
00188
00189
00190
00191 if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc)) < 0)
00192 return (-1);
00193
00194 if (col > 0)
00195 if (putc('\n', fp) < 0)
00196 return (-1);
00197
00198
00199
00200
00201
00202 return (0);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 stp_mxmlSaveString(stp_mxml_node_t *node,
00216 char *buffer,
00217 int bufsize,
00218 int (*cb)(stp_mxml_node_t *, int))
00219
00220 {
00221 int col;
00222 char *ptr[2];
00223
00224
00225
00226
00227
00228
00229 ptr[0] = buffer;
00230 ptr[1] = buffer + bufsize;
00231
00232 if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc)) < 0)
00233 return (-1);
00234
00235 if (col > 0)
00236 mxml_string_putc('\n', ptr);
00237
00238
00239
00240
00241
00242 if (ptr[0] >= ptr[1])
00243 buffer[bufsize - 1] = '\0';
00244 else
00245 ptr[0][0] = '\0';
00246
00247
00248
00249
00250
00251 return (ptr[0] - buffer);
00252 }
00253
00254
00255
00256
00257
00258
00259 static int
00260 mxml_add_char(int ch,
00261 char **bufptr,
00262 char **buffer,
00263 int *bufsize)
00264 {
00265 char *newbuffer;
00266
00267
00268 if (*bufptr >= (*buffer + *bufsize - 1))
00269 {
00270
00271
00272
00273
00274 if (*bufsize < 1024)
00275 (*bufsize) *= 2;
00276 else
00277 (*bufsize) += 1024;
00278
00279 if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
00280 {
00281 free(*buffer);
00282
00283 fprintf(stderr, "Unable to expand string buffer to %d bytes!\n",
00284 *bufsize);
00285
00286 return (-1);
00287 }
00288
00289 *bufptr = newbuffer + (*bufptr - *buffer);
00290 *buffer = newbuffer;
00291 }
00292
00293 *(*bufptr)++ = ch;
00294
00295 return (0);
00296 }
00297
00298
00299
00300
00301
00302
00303 static int
00304 mxml_file_getc(void *p)
00305 {
00306 return (getc((FILE *)p));
00307 }
00308
00309
00310
00311
00312
00313
00314 static int
00315 mxml_file_putc(int ch,
00316 void *p)
00317 {
00318 return (putc(ch, (FILE *)p));
00319 }
00320
00321
00322
00323
00324
00325
00326 static stp_mxml_node_t *
00327 mxml_load_data(stp_mxml_node_t *top,
00328 void *p,
00329 stp_mxml_type_t (*cb)(stp_mxml_node_t *),
00330
00331 int (*getc_cb)(void *))
00332
00333 {
00334 stp_mxml_node_t *node,
00335 *parent;
00336 int ch,
00337 whitespace;
00338 char *buffer,
00339 *bufptr;
00340 int bufsize;
00341 stp_mxml_type_t type;
00342
00343
00344
00345
00346
00347
00348 if ((buffer = malloc(64)) == NULL)
00349 {
00350 fputs("Unable to allocate string buffer!\n", stderr);
00351 return (NULL);
00352 }
00353
00354 bufsize = 64;
00355 bufptr = buffer;
00356 parent = top;
00357 whitespace = 0;
00358
00359 if (cb && parent)
00360 type = (*cb)(parent);
00361 else
00362 type = STP_MXML_TEXT;
00363
00364 while ((ch = (*getc_cb)(p)) != EOF)
00365 {
00366 if ((ch == '<' || (isspace(ch) && type != STP_MXML_OPAQUE)) && bufptr > buffer)
00367 {
00368
00369
00370
00371
00372 *bufptr = '\0';
00373
00374 switch (type)
00375 {
00376 case STP_MXML_INTEGER :
00377 node = stp_mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
00378 break;
00379
00380 case STP_MXML_OPAQUE :
00381 node = stp_mxmlNewOpaque(parent, buffer);
00382 break;
00383
00384 case STP_MXML_REAL :
00385 node = stp_mxmlNewReal(parent, strtod(buffer, &bufptr));
00386 break;
00387
00388 case STP_MXML_TEXT :
00389 node = stp_mxmlNewText(parent, whitespace, buffer);
00390 break;
00391
00392 default :
00393 node = NULL;
00394 break;
00395 }
00396
00397 if (*bufptr)
00398 {
00399
00400
00401
00402
00403 fprintf(stderr, "Bad %s value '%s' in parent <%s>!\n",
00404 type == STP_MXML_INTEGER ? "integer" : "real", buffer,
00405 parent ? parent->value.element.name : "null");
00406 break;
00407 }
00408
00409 bufptr = buffer;
00410 whitespace = isspace(ch) && type == STP_MXML_TEXT;
00411
00412 if (!node)
00413 {
00414
00415
00416
00417
00418 fprintf(stderr, "Unable to add value node of type %d to parent <%s>!\n",
00419 type, parent ? parent->value.element.name : "null");
00420 break;
00421 }
00422 }
00423 else if (isspace(ch) && type == STP_MXML_TEXT)
00424 whitespace = 1;
00425
00426
00427
00428
00429
00430
00431 if (ch == '<' && whitespace && type == STP_MXML_TEXT)
00432 {
00433 stp_mxmlNewText(parent, whitespace, "");
00434 whitespace = 0;
00435 }
00436
00437 if (ch == '<')
00438 {
00439
00440
00441
00442
00443 bufptr = buffer;
00444
00445 while ((ch = (*getc_cb)(p)) != EOF)
00446 if (isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
00447 break;
00448 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
00449 {
00450 free(buffer);
00451 return (NULL);
00452 }
00453 else if ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3))
00454 break;
00455
00456 *bufptr = '\0';
00457
00458 if (!strcmp(buffer, "!--"))
00459 {
00460
00461
00462
00463
00464 while ((ch = (*getc_cb)(p)) != EOF)
00465 {
00466 if (ch == '>' && bufptr > (buffer + 4) &&
00467 !strncmp(bufptr - 2, "--", 2))
00468 break;
00469 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
00470 {
00471 free(buffer);
00472 return (NULL);
00473 }
00474 }
00475
00476
00477
00478
00479
00480 if (ch != '>')
00481 break;
00482
00483
00484
00485
00486
00487 *bufptr = '\0';
00488
00489 if (!stp_mxmlNewElement(parent, buffer))
00490 {
00491
00492
00493
00494
00495 fprintf(stderr, "Unable to add comment node to parent <%s>!\n",
00496 parent ? parent->value.element.name : "null");
00497 break;
00498 }
00499 }
00500 else if (buffer[0] == '!')
00501 {
00502
00503
00504
00505
00506 do
00507 {
00508 if (ch == '>')
00509 break;
00510 else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
00511 {
00512 free(buffer);
00513 return (NULL);
00514 }
00515 }
00516 while ((ch = (*getc_cb)(p)) != EOF);
00517
00518
00519
00520
00521
00522 if (ch != '>')
00523 break;
00524
00525
00526
00527
00528
00529 *bufptr = '\0';
00530
00531 node = stp_mxmlNewElement(parent, buffer);
00532 if (!node)
00533 {
00534
00535
00536
00537
00538 fprintf(stderr, "Unable to add declaration node to parent <%s>!\n",
00539 parent ? parent->value.element.name : "null");
00540 break;
00541 }
00542
00543
00544
00545
00546
00547 parent = node;
00548
00549 if (cb && parent)
00550 type = (*cb)(parent);
00551 }
00552 else if (buffer[0] == '/')
00553 {
00554
00555
00556
00557
00558 if (!parent || strcmp(buffer + 1, parent->value.element.name))
00559 {
00560
00561
00562
00563
00564 fprintf(stderr, "Mismatched close tag <%s> under parent <%s>!\n",
00565 buffer, parent->value.element.name);
00566 break;
00567 }
00568
00569
00570
00571
00572
00573 while (ch != '>' && ch != EOF)
00574 ch = (*getc_cb)(p);
00575
00576
00577
00578
00579
00580 parent = parent->parent;
00581
00582 if (cb && parent)
00583 type = (*cb)(parent);
00584 }
00585 else
00586 {
00587
00588
00589
00590
00591 node = stp_mxmlNewElement(parent, buffer);
00592
00593 if (!node)
00594 {
00595
00596
00597
00598
00599 fprintf(stderr, "Unable to add element node to parent <%s>!\n",
00600 parent ? parent->value.element.name : "null");
00601 break;
00602 }
00603
00604 if (isspace(ch))
00605 ch = mxml_parse_element(node, p, getc_cb);
00606 else if (ch == '/')
00607 {
00608 if ((ch = (*getc_cb)(p)) != '>')
00609 {
00610 fprintf(stderr, "Expected > but got '%c' instead for element <%s/>!\n",
00611 ch, buffer);
00612 break;
00613 }
00614
00615 ch = '/';
00616 }
00617
00618 if (ch == EOF)
00619 break;
00620
00621 if (ch != '/')
00622 {
00623
00624
00625
00626
00627 parent = node;
00628
00629 if (cb && parent)
00630 type = (*cb)(parent);
00631 }
00632 }
00633
00634 bufptr = buffer;
00635 }
00636 else if (ch == '&')
00637 {
00638
00639
00640
00641
00642
00643 char entity[64],
00644 *entptr;
00645
00646
00647 entity[0] = ch;
00648 entptr = entity + 1;
00649
00650 while ((ch = (*getc_cb)(p)) != EOF)
00651 if (!isalnum(ch) && ch != '#')
00652 break;
00653 else if (entptr < (entity + sizeof(entity) - 1))
00654 *entptr++ = ch;
00655 else
00656 {
00657 fprintf(stderr, "Entity name too long under parent <%s>!\n",
00658 parent ? parent->value.element.name : "null");
00659 break;
00660 }
00661
00662 *entptr = '\0';
00663
00664 if (ch != ';')
00665 {
00666 fprintf(stderr, "Entity name \"%s\" not terminated under parent <%s>!\n",
00667 entity, parent ? parent->value.element.name : "null");
00668 break;
00669 }
00670
00671 if (entity[1] == '#')
00672 {
00673 if (entity[2] == 'x')
00674 ch = strtol(entity + 3, NULL, 16);
00675 else
00676 ch = strtol(entity + 2, NULL, 10);
00677 }
00678 else if (!strcmp(entity, "&"))
00679 ch = '&';
00680 else if (!strcmp(entity, ">"))
00681 ch = '>';
00682 else if (!strcmp(entity, "<"))
00683 ch = '<';
00684 else if (!strcmp(entity, " "))
00685 ch = 0xa0;
00686 else if (!strcmp(entity, """))
00687 ch = '\"';
00688 else
00689 {
00690 fprintf(stderr, "Entity name \"%s;\" not supported under parent <%s>!\n",
00691 entity, parent ? parent->value.element.name : "null");
00692 break;
00693 }
00694
00695 if (ch < 128)
00696 {
00697
00698
00699
00700
00701 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
00702 {
00703 free(buffer);
00704 return (NULL);
00705 }
00706 }
00707 else
00708 {
00709
00710
00711
00712
00713 if (ch < 2048)
00714 {
00715 if (mxml_add_char(0xc0 | (ch >> 6), &bufptr, &buffer, &bufsize))
00716 {
00717 free(buffer);
00718 return (NULL);
00719 }
00720 if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
00721 {
00722 free(buffer);
00723 return (NULL);
00724 }
00725 }
00726 else if (ch < 65536)
00727 {
00728 if (mxml_add_char(0xe0 | (ch >> 12), &bufptr, &buffer, &bufsize))
00729 {
00730 free(buffer);
00731 return (NULL);
00732 }
00733 if (mxml_add_char(0x80 | ((ch >> 6) & 63), &bufptr, &buffer, &bufsize))
00734 {
00735 free(buffer);
00736 return (NULL);
00737 }
00738 if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
00739 {
00740 free(buffer);
00741 return (NULL);
00742 }
00743 }
00744 else
00745 {
00746 if (mxml_add_char(0xf0 | (ch >> 18), &bufptr, &buffer, &bufsize))
00747 {
00748 free(buffer);
00749 return (NULL);
00750 }
00751 if (mxml_add_char(0x80 | ((ch >> 12) & 63), &bufptr, &buffer, &bufsize))
00752 {
00753 free(buffer);
00754 return (NULL);
00755 }
00756 if (mxml_add_char(0x80 | ((ch >> 6) & 63), &bufptr, &buffer, &bufsize))
00757 {
00758 free(buffer);
00759 return (NULL);
00760 }
00761 if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
00762 {
00763 free(buffer);
00764 return (NULL);
00765 }
00766 }
00767 }
00768 }
00769 else if (type == STP_MXML_OPAQUE || !isspace(ch))
00770 {
00771
00772
00773
00774
00775 if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
00776 {
00777 free(buffer);
00778 return (NULL);
00779 }
00780 }
00781 }
00782
00783
00784
00785
00786
00787 free(buffer);
00788
00789
00790
00791
00792
00793 if (parent)
00794 {
00795 while (parent->parent != top)
00796 parent = parent->parent;
00797 }
00798
00799 return (parent);
00800 }
00801
00802
00803
00804
00805
00806
00807 static int
00808 mxml_parse_element(stp_mxml_node_t *node,
00809 void *p,
00810 int (*getc_cb)(void *))
00811
00812 {
00813 int ch,
00814 quote;
00815 char *name,
00816 *value,
00817 *ptr;
00818 int namesize,
00819 valsize;
00820
00821
00822
00823
00824
00825
00826 if ((name = malloc(64)) == NULL)
00827 {
00828 fputs("Unable to allocate memory for name!\n", stderr);
00829 return (EOF);
00830 }
00831
00832 namesize = 64;
00833
00834 if ((value = malloc(64)) == NULL)
00835 {
00836 free(name);
00837 fputs("Unable to allocate memory for value!\n", stderr);
00838 return (EOF);
00839 }
00840
00841 valsize = 64;
00842
00843
00844
00845
00846
00847 while ((ch = (*getc_cb)(p)) != EOF)
00848 {
00849 #ifdef DEBUG
00850 fprintf(stderr, "parse_element: ch='%c'\n", ch);
00851 #endif
00852
00853
00854
00855
00856
00857 if (isspace(ch))
00858 continue;
00859
00860
00861
00862
00863
00864 if (ch == '/' || ch == '?')
00865 {
00866
00867
00868
00869
00870 quote = (*getc_cb)(p);
00871
00872 if (quote != '>')
00873 {
00874 fprintf(stderr, "Expected '>' after '%c' for element %s, but got '%c'!\n",
00875 ch, node->value.element.name, quote);
00876 ch = EOF;
00877 }
00878
00879 break;
00880 }
00881 else if (ch == '>')
00882 break;
00883
00884
00885
00886
00887
00888 name[0] = ch;
00889 ptr = name + 1;
00890
00891 while ((ch = (*getc_cb)(p)) != EOF)
00892 if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
00893 break;
00894 else if (mxml_add_char(ch, &ptr, &name, &namesize))
00895 {
00896 free(name);
00897 free(value);
00898 return (EOF);
00899 }
00900
00901 *ptr = '\0';
00902
00903 if (ch == '=')
00904 {
00905
00906
00907
00908
00909 if ((ch = (*getc_cb)(p)) == EOF)
00910 {
00911 fprintf(stderr, "Missing value for attribute '%s' in element %s!\n",
00912 name, node->value.element.name);
00913 return (EOF);
00914 }
00915
00916 if (ch == '\'' || ch == '\"')
00917 {
00918
00919
00920
00921
00922 quote = ch;
00923 ptr = value;
00924
00925 while ((ch = (*getc_cb)(p)) != EOF)
00926 if (ch == quote)
00927 break;
00928 else if (mxml_add_char(ch, &ptr, &value, &valsize))
00929 {
00930 free(name);
00931 free(value);
00932 return (EOF);
00933 }
00934
00935 *ptr = '\0';
00936 }
00937 else
00938 {
00939
00940
00941
00942
00943 value[0] = ch;
00944 ptr = value + 1;
00945
00946 while ((ch = (*getc_cb)(p)) != EOF)
00947 if (isspace(ch) || ch == '=' || ch == '/' || ch == '>')
00948 break;
00949 else if (mxml_add_char(ch, &ptr, &value, &valsize))
00950 {
00951 free(name);
00952 free(value);
00953 return (EOF);
00954 }
00955
00956 *ptr = '\0';
00957 }
00958 }
00959 else
00960 value[0] = '\0';
00961
00962
00963
00964
00965
00966 if (ch == '/' || ch == '?')
00967 {
00968
00969
00970
00971
00972 quote = (*getc_cb)(p);
00973
00974 if (quote != '>')
00975 {
00976 fprintf(stderr, "Expected '>' after '%c' for element %s, but got '%c'!\n",
00977 ch, node->value.element.name, quote);
00978 ch = EOF;
00979 }
00980
00981 break;
00982 }
00983 else if (ch == '>')
00984 break;
00985
00986
00987
00988
00989
00990 stp_mxmlElementSetAttr(node, name, value);
00991 }
00992
00993
00994
00995
00996
00997 free(name);
00998 free(value);
00999
01000 return (ch);
01001 }
01002
01003
01004
01005
01006
01007
01008 static int
01009 mxml_string_getc(void *p)
01010 {
01011 int ch;
01012 const char **s;
01013
01014
01015 s = (const char **)p;
01016
01017 if ((ch = *s[0]) != 0)
01018 {
01019 (*s)++;
01020 return (ch);
01021 }
01022 else
01023 return (EOF);
01024 }
01025
01026
01027
01028
01029
01030
01031 static int
01032 mxml_string_putc(int ch,
01033 void *p)
01034 {
01035 char **pp;
01036
01037
01038 pp = (char **)p;
01039
01040 if (pp[0] < pp[1])
01041 pp[0][0] = ch;
01042
01043 pp[0] ++;
01044
01045 return (0);
01046 }
01047
01048
01049
01050
01051
01052
01053 static int
01054 mxml_write_node(stp_mxml_node_t *node,
01055 void *p,
01056 int (*cb)(stp_mxml_node_t *, int),
01057
01058 int col,
01059 int (*putc_cb)(int, void *))
01060 {
01061 int i;
01062 stp_mxml_attr_t *attr;
01063 char s[255];
01064
01065
01066 while (node != NULL)
01067 {
01068
01069
01070
01071
01072 switch (node->type)
01073 {
01074 case STP_MXML_ELEMENT :
01075 col = mxml_write_ws(node, p, cb, STP_MXML_WS_BEFORE_OPEN, col, putc_cb);
01076
01077 if ((*putc_cb)('<', p) < 0)
01078 return (-1);
01079 if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
01080 return (-1);
01081
01082 col += strlen(node->value.element.name) + 1;
01083
01084 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
01085 i > 0;
01086 i --, attr ++)
01087 {
01088 if ((col + strlen(attr->name) + strlen(attr->value) + 3) > STP_MXML_WRAP)
01089 {
01090 if ((*putc_cb)('\n', p) < 0)
01091 return (-1);
01092
01093 col = 0;
01094 }
01095 else
01096 {
01097 if ((*putc_cb)(' ', p) < 0)
01098 return (-1);
01099
01100 col ++;
01101 }
01102
01103 if (mxml_write_string(attr->name, p, putc_cb) < 0)
01104 return (-1);
01105 if ((*putc_cb)('=', p) < 0)
01106 return (-1);
01107 if ((*putc_cb)('\"', p) < 0)
01108 return (-1);
01109 if (mxml_write_string(attr->value, p, putc_cb) < 0)
01110 return (-1);
01111 if ((*putc_cb)('\"', p) < 0)
01112 return (-1);
01113
01114 col += strlen(attr->name) + strlen(attr->value) + 3;
01115 }
01116
01117 if (node->child)
01118 {
01119
01120
01121
01122
01123 if (node->value.element.name[0] == '?')
01124 {
01125 if ((*putc_cb)('?', p) < 0)
01126 return (-1);
01127 if ((*putc_cb)('>', p) < 0)
01128 return (-1);
01129 if ((*putc_cb)('\n', p) < 0)
01130 return (-1);
01131
01132 col = 0;
01133 }
01134 else if ((*putc_cb)('>', p) < 0)
01135 return (-1);
01136 else
01137 col ++;
01138
01139 col = mxml_write_ws(node, p, cb, STP_MXML_WS_AFTER_OPEN, col, putc_cb);
01140
01141 if ((col = mxml_write_node(node->child, p, cb, col, putc_cb)) < 0)
01142 return (-1);
01143
01144 if (node->value.element.name[0] != '?' &&
01145 node->value.element.name[0] != '!')
01146 {
01147 col = mxml_write_ws(node, p, cb, STP_MXML_WS_BEFORE_CLOSE, col, putc_cb);
01148
01149 if ((*putc_cb)('<', p) < 0)
01150 return (-1);
01151 if ((*putc_cb)('/', p) < 0)
01152 return (-1);
01153 if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
01154 return (-1);
01155 if ((*putc_cb)('>', p) < 0)
01156 return (-1);
01157
01158 col += strlen(node->value.element.name) + 3;
01159
01160 col = mxml_write_ws(node, p, cb, STP_MXML_WS_AFTER_CLOSE, col, putc_cb);
01161 }
01162 }
01163 else if (node->value.element.name[0] == '!')
01164 {
01165 if ((*putc_cb)('>', p) < 0)
01166 return (-1);
01167 else
01168 col ++;
01169
01170 col = mxml_write_ws(node, p, cb, STP_MXML_WS_AFTER_OPEN, col, putc_cb);
01171 }
01172 else
01173 {
01174 if ((*putc_cb)('/', p) < 0)
01175 return (-1);
01176 if ((*putc_cb)('>', p) < 0)
01177 return (-1);
01178
01179 col += 2;
01180
01181 col = mxml_write_ws(node, p, cb, STP_MXML_WS_AFTER_OPEN, col, putc_cb);
01182 }
01183 break;
01184
01185 case STP_MXML_INTEGER :
01186 if (node->prev)
01187 {
01188 if (col > STP_MXML_WRAP)
01189 {
01190 if ((*putc_cb)('\n', p) < 0)
01191 return (-1);
01192
01193 col = 0;
01194 }
01195 else if ((*putc_cb)(' ', p) < 0)
01196 return (-1);
01197 else
01198 col ++;
01199 }
01200
01201 sprintf(s, "%d", node->value.integer);
01202 if (mxml_write_string(s, p, putc_cb) < 0)
01203 return (-1);
01204
01205 col += strlen(s);
01206 break;
01207
01208 case STP_MXML_OPAQUE :
01209 if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
01210 return (-1);
01211
01212 col += strlen(node->value.opaque);
01213 break;
01214
01215 case STP_MXML_REAL :
01216 if (node->prev)
01217 {
01218 if (col > STP_MXML_WRAP)
01219 {
01220 if ((*putc_cb)('\n', p) < 0)
01221 return (-1);
01222
01223 col = 0;
01224 }
01225 else if ((*putc_cb)(' ', p) < 0)
01226 return (-1);
01227 else
01228 col ++;
01229 }
01230
01231 sprintf(s, "%f", node->value.real);
01232 if (mxml_write_string(s, p, putc_cb) < 0)
01233 return (-1);
01234
01235 col += strlen(s);
01236 break;
01237
01238 case STP_MXML_TEXT :
01239 if (node->value.text.whitespace && col > 0)
01240 {
01241 if (col > STP_MXML_WRAP)
01242 {
01243 if ((*putc_cb)('\n', p) < 0)
01244 return (-1);
01245
01246 col = 0;
01247 }
01248 else if ((*putc_cb)(' ', p) < 0)
01249 return (-1);
01250 else
01251 col ++;
01252 }
01253
01254 if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
01255 return (-1);
01256
01257 col += strlen(node->value.text.string);
01258 break;
01259 }
01260
01261
01262
01263
01264
01265 node = node->next;
01266 }
01267
01268 return (col);
01269 }
01270
01271
01272
01273
01274
01275
01276 static int
01277 mxml_write_string(const char *s,
01278 void *p,
01279 int (*putc_cb)(int, void *))
01280
01281 {
01282 char buf[255],
01283 *bufptr;
01284
01285
01286 while (*s)
01287 {
01288 if (*s == '&')
01289 {
01290 if ((*putc_cb)('&', p) < 0)
01291 return (-1);
01292 if ((*putc_cb)('a', p) < 0)
01293 return (-1);
01294 if ((*putc_cb)('m', p) < 0)
01295 return (-1);
01296 if ((*putc_cb)('p', p) < 0)
01297 return (-1);
01298 if ((*putc_cb)(';', p) < 0)
01299 return (-1);
01300 }
01301 else if (*s == '<')
01302 {
01303 if ((*putc_cb)('&', p) < 0)
01304 return (-1);
01305 if ((*putc_cb)('l', p) < 0)
01306 return (-1);
01307 if ((*putc_cb)('t', p) < 0)
01308 return (-1);
01309 if ((*putc_cb)(';', p) < 0)
01310 return (-1);
01311 }
01312 else if (*s == '>')
01313 {
01314 if ((*putc_cb)('&', p) < 0)
01315 return (-1);
01316 if ((*putc_cb)('g', p) < 0)
01317 return (-1);
01318 if ((*putc_cb)('t', p) < 0)
01319 return (-1);
01320 if ((*putc_cb)(';', p) < 0)
01321 return (-1);
01322 }
01323 else if (*s == '\"')
01324 {
01325 if ((*putc_cb)('&', p) < 0)
01326 return (-1);
01327 if ((*putc_cb)('q', p) < 0)
01328 return (-1);
01329 if ((*putc_cb)('u', p) < 0)
01330 return (-1);
01331 if ((*putc_cb)('o', p) < 0)
01332 return (-1);
01333 if ((*putc_cb)('t', p) < 0)
01334 return (-1);
01335 if ((*putc_cb)(';', p) < 0)
01336 return (-1);
01337 }
01338 else if (*s & 128)
01339 {
01340
01341
01342
01343
01344 int ch;
01345
01346
01347 ch = *s & 255;
01348
01349 if ((ch & 0xe0) == 0xc0)
01350 {
01351 ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
01352 s ++;
01353 }
01354 else if ((ch & 0xf0) == 0xe0)
01355 {
01356 ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
01357 s += 2;
01358 }
01359
01360 if (ch == 0xa0)
01361 {
01362
01363
01364
01365
01366 if ((*putc_cb)('&', p) < 0)
01367 return (-1);
01368 if ((*putc_cb)('n', p) < 0)
01369 return (-1);
01370 if ((*putc_cb)('b', p) < 0)
01371 return (-1);
01372 if ((*putc_cb)('s', p) < 0)
01373 return (-1);
01374 if ((*putc_cb)('p', p) < 0)
01375 return (-1);
01376 if ((*putc_cb)(';', p) < 0)
01377 return (-1);
01378 }
01379 else
01380 {
01381 sprintf(buf, "&#x%x;", ch);
01382
01383 for (bufptr = buf; *bufptr; bufptr ++)
01384 if ((*putc_cb)(*bufptr, p) < 0)
01385 return (-1);
01386 }
01387 }
01388 else if ((*putc_cb)(*s, p) < 0)
01389 return (-1);
01390
01391 s ++;
01392 }
01393
01394 return (0);
01395 }
01396
01397
01398
01399
01400
01401
01402 static int
01403 mxml_write_ws(stp_mxml_node_t *node,
01404 void *p,
01405 int (*cb)(stp_mxml_node_t *, int),
01406
01407 int ws,
01408 int col,
01409 int (*putc_cb)(int, void *))
01410
01411 {
01412 int ch;
01413
01414
01415 if (cb && (ch = (*cb)(node, ws)) != 0)
01416 {
01417 if ((*putc_cb)(ch, p) < 0)
01418 return (-1);
01419 else if (ch == '\n')
01420 col = 0;
01421 else if (ch == '\t')
01422 {
01423 col += STP_MXML_TAB;
01424 col = col - (col % STP_MXML_TAB);
01425 }
01426 else
01427 col ++;
01428 }
01429
01430 return (col);
01431 }
01432
01433
01434
01435
01436