Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# 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