Changeset 1723

Show
Ignore:
Timestamp:
01/10/06 19:59:47
Author:
miyagawa
Message:

merge audrey's changes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • JSON-Syck/trunk/MANIFEST

    r1715 r1723  
    2121META.yml 
    2222node.c 
     23perl_syck.h 
    2324ppport.h 
     25ppport_math.h 
    2426README 
    2527syck.h 
  • JSON-Syck/trunk/Syck.xs

    r1716 r1723  
    1 #include "EXTERN.h" 
    2 #include "perl.h" 
    3 #include "XSUB.h" 
    4 #include "ppport.h" 
    5  
    6 #undef DEBUG /* maybe defined in perl.h */ 
    7 #include <syck.h> 
    8  
    9 /* 
    10 #undef ASSERT 
    11 #include "Storable.xs" 
    12 */ 
    13  
    14 struct emitter_xtra { 
    15     SV* port; 
    16     char* tag; 
    17 }; 
    18  
    19 SV* perl_syck_lookup_sym( SyckParser *p, SYMID v) { 
    20     SV *obj = &PL_sv_undef; 
    21     syck_lookup_sym(p, v, (char **)&obj); 
    22     return obj; 
    23 
    24  
    25 SYMID perl_syck_parser_handler(SyckParser *p, SyckNode *n) { 
    26     SV *sv; 
    27     AV *seq; 
    28     HV *map; 
    29     long i; 
    30  
    31     switch (n->kind) { 
    32         case syck_str_kind: 
    33             if (n->type_id == NULL) { 
    34                 if ((strcmp( n->data.str->ptr, "~" ) == 0) && (n->data.str->style == scalar_plain)) { 
    35                     sv = &PL_sv_undef; 
    36                 } else { 
    37                     sv = newSVpvn(n->data.str->ptr, n->data.str->len); 
    38                 } 
    39             } else if (strcmp( n->type_id, "str" ) == 0 ) { 
    40                 sv = newSVpvn(n->data.str->ptr, n->data.str->len); 
    41             } else if (strcmp( n->type_id, "null" ) == 0 ) { 
    42                 sv = &PL_sv_undef; 
    43             } else if (strcmp( n->type_id, "bool#yes" ) == 0 ) { 
    44                 sv = &PL_sv_yes; 
    45             } else if (strcmp( n->type_id, "bool#no" ) == 0 ) { 
    46                 sv = &PL_sv_no; 
    47             } else if (strcmp( n->type_id, "default" ) == 0 ) { 
    48                 sv = newSVpvn(n->data.str->ptr, n->data.str->len); 
    49             } else if (strcmp( n->type_id, "float#base60" ) == 0 ) { 
    50                 char *ptr, *end; 
    51                 UV sixty = 1; 
    52                 NV total = 0.0; 
    53                 syck_str_blow_away_commas( n ); 
    54                 ptr = n->data.str->ptr; 
    55                 end = n->data.str->ptr + n->data.str->len; 
    56                 while ( end > ptr ) 
    57                 { 
    58                     NV bnum = 0; 
    59                     char *colon = end - 1; 
    60                     while ( colon >= ptr && *colon != ':' ) 
    61                     { 
    62                         colon--; 
    63                     } 
    64                     if ( *colon == ':' ) *colon = '\0'; 
    65  
    66                     bnum = strtod( colon + 1, NULL ); 
    67                     total += bnum * sixty; 
    68                     sixty *= 60; 
    69                     end = colon; 
    70                 } 
    71                 sv = newSVnv(total); 
    72             } else if (strcmp( n->type_id, "float#nan" ) == 0 ) { 
    73                 sv = newSVnv(NV_NAN); 
    74             } else if (strcmp( n->type_id, "float#inf" ) == 0 ) { 
    75                 sv = newSVnv(NV_INF); 
    76             } else if (strcmp( n->type_id, "float#neginf" ) == 0 ) { 
    77                 sv = newSVnv(-NV_INF); 
    78             } else if (strncmp( n->type_id, "float", 5 ) == 0) { 
    79                 NV f; 
    80                 syck_str_blow_away_commas( n ); 
    81                 f = strtod( n->data.str->ptr, NULL ); 
    82                 sv = newSVnv( f ); 
    83             } else if (strcmp( n->type_id, "int#base60" ) == 0 ) { 
    84                 char *ptr, *end; 
    85                 UV sixty = 1; 
    86                 UV total = 0; 
    87                 syck_str_blow_away_commas( n ); 
    88                 ptr = n->data.str->ptr; 
    89                 end = n->data.str->ptr + n->data.str->len; 
    90                 while ( end > ptr ) 
    91                 { 
    92                     long bnum = 0; 
    93                     char *colon = end - 1; 
    94                     while ( colon >= ptr && *colon != ':' ) 
    95                     { 
    96                         colon--; 
    97                     } 
    98                     if ( *colon == ':' ) *colon = '\0'; 
    99  
    100                     bnum = strtol( colon + 1, NULL, 10 ); 
    101                     total += bnum * sixty; 
    102                     sixty *= 60; 
    103                     end = colon; 
    104                 } 
    105                 sv = newSVuv(total); 
    106             } else if (strcmp( n->type_id, "int#hex" ) == 0 ) { 
    107                 STRLEN len = n->data.str->len; 
    108                 syck_str_blow_away_commas( n ); 
    109                 sv = newSVuv( grok_hex( n->data.str->ptr, &len, 0, NULL) ); 
    110             } else if (strcmp( n->type_id, "int#oct" ) == 0 ) { 
    111                 STRLEN len = n->data.str->len; 
    112                 syck_str_blow_away_commas( n ); 
    113                 sv = newSVuv( grok_oct( n->data.str->ptr, &len, 0, NULL) ); 
    114             } else if (strncmp( n->type_id, "int", 3 ) == 0) { 
    115                 UV uv = 0; 
    116                 syck_str_blow_away_commas( n ); 
    117                 grok_number( n->data.str->ptr, n->data.str->len, &uv); 
    118                 sv = newSVuv(uv); 
    119             } else { 
    120                 /* croak("unknown node type: %s", n->type_id); */ 
    121                 sv = newSVpvn(n->data.str->ptr, n->data.str->len); 
    122             } 
    123         break; 
    124  
    125         case syck_seq_kind: 
    126             seq = newAV(); 
    127             for (i = 0; i < n->data.list->idx; i++) { 
    128                 av_push(seq, perl_syck_lookup_sym(p, syck_seq_read(n, i) )); 
    129             } 
    130             sv = newRV_noinc((SV*)seq); 
    131             if (n->type_id) { 
    132                 sv_bless(sv, gv_stashpv(n->type_id + 6, TRUE)); 
    133             } 
    134         break; 
    135  
    136         case syck_map_kind: 
    137             map = newHV(); 
    138             for (i = 0; i < n->data.pairs->idx; i++) { 
    139                 hv_store_ent( 
    140                     map, 
    141                     perl_syck_lookup_sym(p, syck_map_read(n, map_key, i) ), 
    142                     perl_syck_lookup_sym(p, syck_map_read(n, map_value, i) ), 
    143                     0 
    144                 ); 
    145             } 
    146             sv = newRV_noinc((SV*)map); 
    147             if (n->type_id) { 
    148                 sv_bless(sv, gv_stashpv(n->type_id + 5, TRUE)); 
    149             } 
    150         break; 
    151     } 
    152     return syck_add_sym(p, (char *)sv); 
    153 
    154  
    155 void perl_syck_mark_emitter(SyckEmitter *e) { 
    156     return; 
    157 
    158  
    159 void perl_syck_error_handler(SyckParser *p, char *msg) { 
    160     croak(form( "JSON::Syck parser (line %d, column %d): %s",  
    161         p->linect + 1, 
    162         p->cursor - p->lineptr, 
    163         msg )); 
    164 
    165  
    166 static SV * Load(char *s) { 
    167     SV *obj; 
    168     SYMID v; 
    169     SyckParser *parser; 
    170     SV *implicit = GvSV(gv_fetchpv("JSON::Syck::ImplicitTyping", TRUE, SVt_PV)); 
    171  
    172     /* Don't even bother if the string is empty. */ 
    173     if (*s == '\0') { return &PL_sv_undef; } 
    174  
    175     parser = syck_new_parser(); 
    176     syck_parser_str_auto(parser, s, NULL); 
    177     syck_parser_handler(parser, perl_syck_parser_handler); 
    178     syck_parser_error_handler(parser, perl_syck_error_handler); 
    179     syck_parser_implicit_typing(parser, SvTRUE(implicit)); 
    180     syck_parser_taguri_expansion(parser, 0); 
    181     v = syck_parse(parser); 
    182     syck_lookup_sym(parser, v, (char **)&obj); 
    183     syck_free_parser(parser); 
    184     return obj; 
    185 
    186  
    187 void perl_syck_output_handler(SyckEmitter *e, char *str, long len) { 
    188     struct emitter_xtra *bonus = (struct emitter_xtra *)e->bonus; 
    189     sv_catpvn_nomg(bonus->port, str, len); 
    190     e->headless = 1; 
    191 
    192  
    193 void perl_syck_emitter_handler(SyckEmitter *e, st_data_t data) { 
    194     I32  len, i; 
    195     SV*  sv = (SV*)data; 
    196     struct emitter_xtra *bonus = (struct emitter_xtra *)e->bonus; 
    197     char* tag = bonus->tag; 
    198     char* ref = NULL; 
    199  
    200     if (sv == &PL_sv_undef) { 
    201         return syck_emit_scalar(e, "string", scalar_none, 0, 0, 0, "~", 1); 
    202     } 
    203      
    204 #define OBJECT_TAG     "tag:perl:" 
    205      
    206     if (SvMAGICAL(sv)) { 
    207         mg_get(sv); 
    208     } 
    209  
    210     if (sv_isobject(sv)) { 
    211         ref = savepv(sv_reftype(SvRV(sv), TRUE)); 
    212         *tag = '\0'; 
    213         strcat(tag, OBJECT_TAG); 
    214         switch (SvTYPE(SvRV(sv))) { 
    215             case SVt_PVAV: { strcat(tag, "@"); break; } 
    216             case SVt_RV:   { strcat(tag, "$"); break; } 
    217             case SVt_PVCV: { strcat(tag, "code"); break; } 
    218             case SVt_PVGV: { strcat(tag, "glob"); break; } 
    219         } 
    220         strcat(tag, ref); 
    221     } 
    222  
    223 #define OBJOF(a) (*tag ? tag : a) 
    224     switch (SvTYPE(sv)) { 
    225         case SVt_NULL: { return; } 
    226         case SVt_PV: 
    227         case SVt_PVIV: 
    228         case SVt_PVNV: { 
    229             if (SvCUR(sv) > 0) { 
    230                 syck_emit_scalar(e, OBJOF("string"), scalar_2quote, 0, 0, 0, SvPVX(sv), SvCUR(sv)); 
    231             } 
    232             else { 
    233                 syck_emit_scalar(e, OBJOF("string"), scalar_1quote, 0, 0, 0, "", 0); 
    234             } 
    235             break; 
    236         } 
    237         case SVt_IV: 
    238         case SVt_NV: 
    239         case SVt_PVMG: 
    240         case SVt_PVBM: 
    241         case SVt_PVLV: { 
    242             if (sv_len(sv) > 0) { 
    243                 syck_emit_scalar(e, OBJOF("string"), scalar_none, 0, 0, 0, SvPV_nolen(sv), sv_len(sv)); 
    244             } 
    245             else { 
    246                 syck_emit_scalar(e, OBJOF("string"), scalar_1quote, 0, 0, 0, "", 0); 
    247             } 
    248             break; 
    249         } 
    250         case SVt_RV: { 
    251             perl_syck_emitter_handler(e, (st_data_t)SvRV(sv)); 
    252             break; 
    253         } 
    254         case SVt_PVAV: { 
    255             syck_emit_seq(e, OBJOF("array"), seq_inline); 
    256             *tag = '\0'; 
    257             len = av_len((AV*)sv) + 1; 
    258             for (i = 0; i < len; i++) { 
    259                 SV** sav = av_fetch((AV*)sv, i, 0); 
    260                 syck_emit_item( e, (st_data_t)(*sav) ); 
    261             } 
    262             syck_emit_end(e); 
    263             return; 
    264         } 
    265         case SVt_PVHV: { 
    266             syck_emit_map(e, OBJOF("hash"), map_none); 
    267             *tag = '\0'; 
    268 #ifdef HAS_RESTRICTED_HASHES 
    269             len = HvTOTALKEYS((HV*)sv); 
    270 #else 
    271             len = HvKEYS((HV*)sv); 
    272 #endif 
    273             hv_iterinit((HV*)sv); 
    274             for (i = 0; i < len; i++) { 
    275 #ifdef HV_ITERNEXT_WANTPLACEHOLDERS 
    276                 HE *he = hv_iternext_flags((HV*)sv, HV_ITERNEXT_WANTPLACEHOLDERS); 
    277 #else 
    278                 HE *he = hv_iternext((HV*)sv); 
    279 #endif 
    280                 I32 keylen; 
    281                 SV *key = hv_iterkeysv(he); 
    282                 SV *val = hv_iterval((HV*)sv, he); 
    283                 syck_emit_item( e, (st_data_t)key ); 
    284                 syck_emit_item( e, (st_data_t)val ); 
    285             } 
    286             syck_emit_end(e); 
    287             return; 
    288         } 
    289         case SVt_PVCV: { 
    290             /* XXX TODO XXX */ 
    291             syck_emit_scalar(e, OBJOF("string"), scalar_none, 0, 0, 0, SvPV_nolen(sv), sv_len(sv)); 
    292             break; 
    293         } 
    294         case SVt_PVGV: 
    295         case SVt_PVFM: { 
    296             /* XXX TODO XXX */ 
    297             syck_emit_scalar(e, OBJOF("string"), scalar_none, 0, 0, 0, SvPV_nolen(sv), sv_len(sv)); 
    298             break; 
    299         } 
    300         case SVt_PVIO: { 
    301             syck_emit_scalar(e, OBJOF("string"), scalar_none, 0, 0, 0, SvPV_nolen(sv), sv_len(sv)); 
    302             break; 
    303         } 
    304     } 
    305 cleanup: 
    306     *tag = '\0'; 
    307 
    308  
    309 SV* _Dump(SV *sv) { 
    310     struct emitter_xtra *bonus; 
    311     SV* out = newSVpvn("", 0); 
    312     SyckEmitter *emitter = syck_new_emitter(); 
    313     emitter->headless = 1; 
    314  
    315     bonus = emitter->bonus = S_ALLOC_N(struct emitter_xtra, 1); 
    316     bonus->port = out; 
    317     Newz(801, bonus->tag, 512, char); 
    318  
    319     syck_emitter_handler( emitter, perl_syck_emitter_handler ); 
    320     syck_output_handler( emitter, perl_syck_output_handler ); 
    321  
    322     perl_syck_mark_emitter( emitter ); 
    323     syck_emit( emitter, (st_data_t)sv ); 
    324     syck_emitter_flush( emitter, 0 ); 
    325     syck_free_emitter( emitter ); 
    326  
    327     Safefree(bonus->tag); 
    328     return out; 
    329 
     1#include "perl_syck.h" 
     2#undef YAML_IS_JSON 
    3303 
    3314MODULE = JSON::Syck             PACKAGE = JSON::Syck