ext/syck/yaml2byte.c

Go to the documentation of this file.
00001 /*
00002  * yaml2byte.c
00003  *
00004  * $Author: nobu $
00005  *
00006  * Copyright (C) 2003 why the lucky stiff, clark evans
00007  *
00008  *   WARNING WARNING WARNING  --- THIS IS *NOT JUST* PLAYING
00009  *   ANYMORE! -- WHY HAS EMBRACED THIS AS THE REAL THING!
00010  */
00011 #include "ruby/ruby.h"
00012 #include <syck.h>
00013 #include <assert.h>
00014 #define YAMLBYTE_UTF8
00015 #include "yamlbyte.h"
00016 
00017 #include <stdio.h>
00018 #define TRACE0(a)  \
00019     do { printf(a); printf("\n"); fflush(stdout); } while(0)
00020 #define TRACE1(a,b) \
00021     do { printf(a,b); printf("\n"); fflush(stdout); } while(0)
00022 #define TRACE2(a,b,c) \
00023     do { printf(a,b,c); printf("\n"); fflush(stdout); } while(0)
00024 #define TRACE3(a,b,c,d) \
00025     do { printf(a,b,c,d); printf("\n"); fflush(stdout); } while(0)
00026 
00027 /* Reinvent the wheel... */
00028 #define CHUNKSIZE 64
00029 #define HASH ((long)0xCAFECAFE)
00030 typedef struct {
00031    long hash;
00032    char *buffer;
00033    long length;
00034    long remaining;
00035    int  printed;
00036 } bytestring_t;
00037 bytestring_t *bytestring_alloc(void) {
00038     bytestring_t *ret;
00039     /*TRACE0("bytestring_alloc()");*/
00040     ret = S_ALLOC(bytestring_t);
00041     ret->hash   = HASH;
00042     ret->length = CHUNKSIZE;
00043     ret->remaining = ret->length;
00044     ret->buffer = S_ALLOC_N(char, ret->length + 1 );
00045     ret->buffer[0] = 0;
00046     ret->printed = 0;
00047     return ret;
00048 }
00049 void bytestring_append(bytestring_t *str, char code,
00050                        char *start, char *finish)
00051 {
00052     long grow;
00053     long length = 2;   /* CODE + LF */
00054     char *curr;
00055     assert(str && HASH == str->hash);
00056     /*TRACE0("bytestring_append()");*/
00057     if(start) {
00058         if(!finish)
00059             finish = start + strlen(start);
00060         length += (finish-start);
00061     }
00062     if(length > str->remaining) {
00063         grow = (length - str->remaining) + CHUNKSIZE;
00064         str->remaining += grow;
00065         str->length    += grow;
00066         S_REALLOC_N( str->buffer, char, str->length + 1 );
00067         assert(str->buffer);
00068     }
00069     curr = str->buffer + (str->length - str->remaining);
00070     *curr = code;
00071     curr += 1;
00072     if(start)
00073         while(start < finish)
00074             *curr ++ = *start ++;
00075     *curr = '\n';
00076     curr += 1;
00077     *curr = 0;
00078     str->remaining = str->remaining - length;
00079     assert( (str->buffer + str->length) - str->remaining );
00080 }
00081 void bytestring_extend(bytestring_t *str, bytestring_t *ext)
00082 {
00083     char *from;
00084     char *curr;
00085     char *stop;
00086     long grow;
00087     long length;
00088     assert(str && HASH == str->hash);
00089     assert(ext && HASH == ext->hash);
00090     if(ext->printed) {
00091         assert(ext->buffer[0] ==YAMLBYTE_ANCHOR);
00092         curr = ext->buffer;
00093         while( '\n' != *curr)
00094             curr++;
00095         bytestring_append(str, YAMLBYTE_ALIAS, ext->buffer + 1, curr);
00096     } else {
00097         ext->printed = 1;
00098         length  = (ext->length - ext->remaining);
00099         if(length > str->remaining) {
00100             grow = (length - str->remaining) + CHUNKSIZE;
00101             str->remaining += grow;
00102             str->length    += grow;
00103             S_REALLOC_N( str->buffer, char, str->length + 1 );
00104         }
00105         curr = str->buffer + (str->length - str->remaining);
00106         from = ext->buffer;
00107         stop = ext->buffer + length;
00108         while( from < stop )
00109             *curr ++ = *from ++;
00110         *curr = 0;
00111         str->remaining = str->remaining - length;
00112         assert( (str->buffer + str->length) - str->remaining );
00113     }
00114 }
00115 
00116 /* convert SyckNode into yamlbyte_buffer_t objects */
00117 SYMID
00118 syck_yaml2byte_handler(p, n)
00119     SyckParser *p;
00120     SyckNode *n;
00121 {
00122     SYMID oid;
00123     long i;
00124     char ch;
00125     char nextcode;
00126     char *start;
00127     char *current;
00128     char *finish;
00129     bytestring_t *val = NULL;
00130     bytestring_t *sav = NULL;
00131     void *data;
00132     /*TRACE0("syck_yaml2byte_handler()");*/
00133     val = bytestring_alloc();
00134     if(n->anchor) bytestring_append(val,YAMLBYTE_ANCHOR, n->anchor, NULL);
00135     if ( n->type_id )
00136     {
00137         if ( p->taguri_expansion )
00138         {
00139             bytestring_append(val,YAMLBYTE_TRANSFER, n->type_id, NULL);
00140         }
00141         else
00142         {
00143             char *type_tag = S_ALLOC_N( char, strlen( n->type_id ) + 1 );
00144             type_tag[0] = '\0';
00145             strcat( type_tag, "!" );
00146             strcat( type_tag, n->type_id );
00147             bytestring_append( val, YAMLBYTE_TRANSFER, type_tag, NULL);
00148             S_FREE(type_tag);
00149         }
00150     }
00151     switch (n->kind)
00152     {
00153         case syck_str_kind:
00154             nextcode = YAMLBYTE_SCALAR;
00155             start  = n->data.str->ptr;
00156             finish = start + n->data.str->len - 1;
00157             current = start;
00158             /*TRACE2("SCALAR: %s %d", start, n->data.str->len); */
00159             while(1) {
00160                 ch = *current;
00161                 if('\n' == ch || 0 == ch || current > finish) {
00162                     if(current >= start) {
00163                         bytestring_append(val, nextcode, start, current);
00164                         nextcode = YAMLBYTE_CONTINUE;
00165                     }
00166                     start = current + 1;
00167                     if(current > finish)
00168                     {
00169                         break;
00170                     }
00171                     else if('\n' == ch )
00172                     {
00173                         bytestring_append(val,YAMLBYTE_NEWLINE,NULL,NULL);
00174                     }
00175                     else if(0 == ch)
00176                     {
00177                         bytestring_append(val,YAMLBYTE_NULLCHAR,NULL,NULL);
00178                     }
00179                     else
00180                     {
00181                         assert("oops");
00182                     }
00183                 }
00184                 current += 1;
00185             }
00186         break;
00187         case syck_seq_kind:
00188             bytestring_append(val,YAMLBYTE_SEQUENCE,NULL,NULL);
00189             for ( i = 0; i < n->data.list->idx; i++ )
00190             {
00191                 oid = syck_seq_read( n, i );
00192                 if (syck_lookup_sym( p, oid, &data )) sav = data;
00193                 bytestring_extend(val, sav);
00194             }
00195             bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
00196         break;
00197         case syck_map_kind:
00198             bytestring_append(val,YAMLBYTE_MAPPING,NULL,NULL);
00199             for ( i = 0; i < n->data.pairs->idx; i++ )
00200             {
00201                 oid = syck_map_read( n, map_key, i );
00202                 if (syck_lookup_sym( p, oid, &data )) sav = data;
00203                 bytestring_extend(val, sav);
00204                 oid = syck_map_read( n, map_value, i );
00205                 if (syck_lookup_sym( p, oid, &data )) sav = data;
00206                 bytestring_extend(val, sav);
00207             }
00208             bytestring_append(val,YAMLBYTE_END_BRANCH,NULL,NULL);
00209         break;
00210     }
00211     oid = syck_add_sym( p, (char *) val );
00212     /*TRACE1("Saving: %s", val->buffer );*/
00213     return oid;
00214 }
00215 
00216 char *
00217 syck_yaml2byte(char *yamlstr)
00218 {
00219     SYMID oid;
00220     char *ret;
00221     bytestring_t *sav;
00222     void *data;
00223 
00224     SyckParser *parser = syck_new_parser();
00225     syck_parser_str_auto( parser, yamlstr, NULL );
00226     syck_parser_handler( parser, syck_yaml2byte_handler );
00227     syck_parser_error_handler( parser, NULL );
00228     syck_parser_implicit_typing( parser, 1 );
00229     syck_parser_taguri_expansion( parser, 1 );
00230     oid = syck_parse( parser );
00231 
00232     if ( syck_lookup_sym( parser, oid, &data ) ) {
00233         sav = data;
00234         ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
00235         ret[0] = '\0';
00236         strcat( ret, "D\n" );
00237         strcat( ret, sav->buffer );
00238     }
00239     else
00240     {
00241         ret = NULL;
00242     }
00243 
00244     syck_free_parser( parser );
00245     return ret;
00246 }
00247 
00248 #ifdef TEST_YBEXT
00249 #include <stdio.h>
00250 int main() {
00251    char *yaml = "test: 1\nand: \"with new\\nline\\n\"\nalso: &3 three\nmore: *3";
00252    printf("--- # YAML \n");
00253    printf(yaml);
00254    printf("\n...\n");
00255    printf(syck_yaml2byte(yaml));
00256    return 0;
00257 }
00258 #endif
00259 
00260 

Generated on Wed Aug 10 09:17:05 2011 for Ruby by  doxygen 1.4.7