зеркало из https://github.com/github/ruby.git
Initial checkin of YAML substances.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3772 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
605adb86e2
Коммит
55f4dc4c9a
|
@ -0,0 +1,5 @@
|
|||
require 'mkmf'
|
||||
|
||||
have_header( "st.h" )
|
||||
create_makefile( "syck" )
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,79 @@
|
|||
/* A Bison parser, made from gram.y, by GNU bison 1.75. */
|
||||
|
||||
/* Skeleton parser for Yacc-like parsing with Bison,
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* As a special exception, when this file is copied by Bison into a
|
||||
Bison output file, you may use that output file without restriction.
|
||||
This special exception was added by the Free Software Foundation
|
||||
in version 1.24 of Bison. */
|
||||
|
||||
#ifndef BISON_Y_TAB_H
|
||||
# define BISON_Y_TAB_H
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
ANCHOR = 258,
|
||||
ALIAS = 259,
|
||||
TRANSFER = 260,
|
||||
ITRANSFER = 261,
|
||||
WORD = 262,
|
||||
PLAIN = 263,
|
||||
BLOCK = 264,
|
||||
DOCSEP = 265,
|
||||
IOPEN = 266,
|
||||
INDENT = 267,
|
||||
IEND = 268
|
||||
};
|
||||
#endif
|
||||
#define ANCHOR 258
|
||||
#define ALIAS 259
|
||||
#define TRANSFER 260
|
||||
#define ITRANSFER 261
|
||||
#define WORD 262
|
||||
#define PLAIN 263
|
||||
#define BLOCK 264
|
||||
#define DOCSEP 265
|
||||
#define IOPEN 266
|
||||
#define INDENT 267
|
||||
#define IEND 268
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef YYSTYPE
|
||||
#line 23 "gram.y"
|
||||
typedef union {
|
||||
SYMID nodeId;
|
||||
SyckNode *nodeData;
|
||||
char *name;
|
||||
} yystype;
|
||||
/* Line 1281 of /usr/local/share/bison/yacc.c. */
|
||||
#line 72 "y.tab.h"
|
||||
# define YYSTYPE yystype
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* not BISON_Y_TAB_H */
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
//
|
||||
// handler.h
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
|
||||
#include "syck.h"
|
||||
|
||||
SYMID
|
||||
syck_hdlr_add_node( SyckParser *p, SyckNode *n )
|
||||
{
|
||||
SYMID id;
|
||||
if ( ! n->id )
|
||||
{
|
||||
n->id = (p->handler)( p, n );
|
||||
}
|
||||
id = n->id;
|
||||
|
||||
if ( n->anchor == NULL )
|
||||
{
|
||||
syck_free_node( n );
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n )
|
||||
{
|
||||
n->anchor = a;
|
||||
st_insert( p->anchors, (st_data_t)a, (st_data_t)n );
|
||||
return n;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_hdlr_add_alias( SyckParser *p, char *a )
|
||||
{
|
||||
SyckNode *n;
|
||||
|
||||
if ( st_lookup( p->anchors, (st_data_t)a, (st_data_t *)&n ) )
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
return syck_new_str( "..." );
|
||||
}
|
||||
|
||||
void
|
||||
syck_add_transfer( char *uri, SyckNode *n, int taguri )
|
||||
{
|
||||
char *comma = NULL;
|
||||
char *slash = uri;
|
||||
char *domain = NULL;
|
||||
|
||||
if ( taguri == 0 )
|
||||
{
|
||||
n->type_id = uri;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( uri[0] == '!' )
|
||||
{
|
||||
syck_xprivate( n, uri + 1, strlen( uri ) - 1 );
|
||||
S_FREE( uri );
|
||||
return;
|
||||
}
|
||||
|
||||
while ( *(++slash) != '\0' )
|
||||
{
|
||||
if ( *slash == '/' )
|
||||
break;
|
||||
|
||||
if ( *slash == ',' )
|
||||
comma = slash;
|
||||
}
|
||||
|
||||
if ( *slash == '\0' )
|
||||
{
|
||||
syck_taguri( n, "yaml.org,2002", uri, strlen( uri ) );
|
||||
}
|
||||
else if ( comma == NULL )
|
||||
{
|
||||
domain = S_ALLOC_N( char, ( slash - uri ) + 15 );
|
||||
domain[0] = '\0';
|
||||
strncat( domain, uri, slash - uri );
|
||||
strcat( domain, ".yaml.org,2002" );
|
||||
syck_taguri( n, domain, slash + 1, strlen( uri ) - ( slash - uri + 1 ) );
|
||||
S_FREE( domain );
|
||||
}
|
||||
else
|
||||
{
|
||||
domain = S_ALLOC_N( char, slash - uri );
|
||||
domain[0] = '\0';
|
||||
strncat( domain, uri, slash - uri );
|
||||
syck_taguri( n, domain, slash + 1, strlen( uri ) - ( slash - uri + 1 ) );
|
||||
S_FREE( domain );
|
||||
}
|
||||
S_FREE( uri );
|
||||
}
|
||||
|
||||
void
|
||||
syck_xprivate( SyckNode *n, char *type_id, int type_len )
|
||||
{
|
||||
if ( n->type_id != NULL )
|
||||
S_FREE( n->type_id );
|
||||
|
||||
n->type_id = S_ALLOC_N( char, type_len + 14 );
|
||||
n->type_id[0] = '\0';
|
||||
strcat( n->type_id, "x-private:" );
|
||||
strncat( n->type_id, type_id, type_len );
|
||||
}
|
||||
|
||||
void
|
||||
syck_taguri( SyckNode *n, char *domain, char *type_id, int type_len )
|
||||
{
|
||||
if ( n->type_id != NULL )
|
||||
S_FREE( n->type_id );
|
||||
|
||||
n->type_id = S_ALLOC_N( char, strlen( domain ) + type_len + 14 );
|
||||
n->type_id[0] = '\0';
|
||||
strcat( n->type_id, "taguri:" );
|
||||
strcat( n->type_id, domain );
|
||||
strcat( n->type_id, ":" );
|
||||
strncat( n->type_id, type_id, type_len );
|
||||
}
|
||||
|
||||
int
|
||||
syck_try_implicit( SyckNode *n )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
syck_fold_format( struct SyckStr *n, int blockType, int indt_len, int nlDisp )
|
||||
{
|
||||
char *spc;
|
||||
char *eol = NULL;
|
||||
char *first_nl = NULL;
|
||||
char *fc = n->ptr;
|
||||
int keep_nl = 0;
|
||||
int nl_count = 0;
|
||||
|
||||
//
|
||||
// Scan the sucker for newlines and strip indent
|
||||
//
|
||||
while ( fc < n->ptr + n->len )
|
||||
{
|
||||
if ( *fc == '\n' )
|
||||
{
|
||||
spc = fc;
|
||||
while ( *(++spc) == ' ' )
|
||||
{
|
||||
if ( blockType != BLOCK_PLAIN && spc - fc > indt_len )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( blockType != BLOCK_LIT && *spc != ' ' )
|
||||
{
|
||||
if ( eol != NULL ) fc = eol;
|
||||
if ( first_nl == NULL && keep_nl == 1 )
|
||||
{
|
||||
first_nl = fc;
|
||||
*first_nl = ' ';
|
||||
}
|
||||
if ( nl_count == 1 )
|
||||
{
|
||||
*first_nl = '\n';
|
||||
keep_nl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fc += keep_nl;
|
||||
if ( fc != spc && ( n->len - ( spc - n->ptr ) ) > 0 )
|
||||
{
|
||||
S_MEMMOVE( fc, spc, char, n->len - ( spc - n->ptr ) );
|
||||
}
|
||||
|
||||
n->len -= spc - fc;
|
||||
keep_nl = 1;
|
||||
eol = NULL;
|
||||
nl_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// eol tracks the last space on a line
|
||||
//
|
||||
if ( *fc == ' ' )
|
||||
{
|
||||
if ( eol == NULL ) eol = fc;
|
||||
}
|
||||
else
|
||||
{
|
||||
eol = NULL;
|
||||
}
|
||||
first_nl = NULL;
|
||||
nl_count = 0;
|
||||
fc++;
|
||||
}
|
||||
}
|
||||
|
||||
n->ptr[n->len] = '\n';
|
||||
|
||||
//
|
||||
// Chomp or keep?
|
||||
//
|
||||
if ( nlDisp != NL_KEEP )
|
||||
{
|
||||
fc = n->ptr + n->len - 1;
|
||||
while ( *fc == '\n' )
|
||||
fc--;
|
||||
|
||||
if ( nlDisp != NL_CHOMP )
|
||||
fc += 1;
|
||||
|
||||
n->len = fc - n->ptr + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Force last line break which I gave back
|
||||
// to the tokenizer.
|
||||
//
|
||||
n->len++;
|
||||
n->ptr[n->len] = '\n';
|
||||
}
|
||||
n->ptr[ n->len ] = '\0';
|
||||
}
|
||||
|
|
@ -0,0 +1,860 @@
|
|||
/* Generated by re2c 0.5 on Mon Apr 21 23:42:24 2003 */
|
||||
#line 1 "lib/implicit.re"
|
||||
//
|
||||
// implicit.re
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
|
||||
#include "syck.h"
|
||||
|
||||
#define YYCTYPE char
|
||||
#define YYCURSOR cursor
|
||||
#define YYMARKER marker
|
||||
#define YYLIMIT limit
|
||||
#define YYFILL(n)
|
||||
|
||||
#define TAG_IMPLICIT( tid ) \
|
||||
if ( taguri == 1 ) \
|
||||
{ \
|
||||
syck_taguri( n, "yaml.org,2002", tid, strlen( tid ) ); \
|
||||
} else { \
|
||||
n->type_id = syck_strndup( tid, strlen( tid ) ); \
|
||||
} \
|
||||
return;
|
||||
|
||||
void
|
||||
try_tag_implicit( SyckNode *n, int taguri )
|
||||
{
|
||||
char *cursor, *limit, *marker;
|
||||
if ( n->kind != syck_str_kind )
|
||||
return;
|
||||
|
||||
cursor = n->data.str->ptr;
|
||||
limit = cursor + n->data.str->len;
|
||||
|
||||
{
|
||||
YYCTYPE yych;
|
||||
unsigned int yyaccept;
|
||||
static unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 193, 0, 4, 0,
|
||||
215, 231, 231, 231, 231, 231, 231, 231,
|
||||
167, 167, 0, 0, 0, 0, 0, 0,
|
||||
0, 128, 128, 128, 128, 128, 128, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 128, 128, 128, 128, 128, 128, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
goto yy0;
|
||||
yy1: ++YYCURSOR;
|
||||
yy0:
|
||||
if((YYLIMIT - YYCURSOR) < 26) YYFILL(26);
|
||||
yych = *YYCURSOR;
|
||||
if(yych <= 'S'){
|
||||
if(yych <= '/'){
|
||||
if(yych <= '+'){
|
||||
if(yych <= '\000') goto yy2;
|
||||
if(yych <= '*') goto yy20;
|
||||
goto yy15;
|
||||
} else {
|
||||
if(yych <= ',') goto yy20;
|
||||
if(yych <= '-') goto yy16;
|
||||
if(yych <= '.') goto yy19;
|
||||
goto yy20;
|
||||
}
|
||||
} else {
|
||||
if(yych <= 'F'){
|
||||
if(yych <= '0') goto yy17;
|
||||
if(yych <= '9') goto yy18;
|
||||
if(yych <= 'E') goto yy20;
|
||||
goto yy14;
|
||||
} else {
|
||||
if(yych <= 'M') goto yy20;
|
||||
if(yych <= 'N') goto yy6;
|
||||
if(yych <= 'O') goto yy12;
|
||||
goto yy20;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(yych <= 'n'){
|
||||
if(yych <= 'Y'){
|
||||
if(yych <= 'T') goto yy8;
|
||||
if(yych <= 'X') goto yy20;
|
||||
goto yy10;
|
||||
} else {
|
||||
if(yych == 'f') goto yy13;
|
||||
if(yych <= 'm') goto yy20;
|
||||
goto yy5;
|
||||
}
|
||||
} else {
|
||||
if(yych <= 'x'){
|
||||
if(yych <= 'o') goto yy11;
|
||||
if(yych == 't') goto yy7;
|
||||
goto yy20;
|
||||
} else {
|
||||
if(yych <= 'y') goto yy9;
|
||||
if(yych == '~') goto yy3;
|
||||
goto yy20;
|
||||
}
|
||||
}
|
||||
}
|
||||
yy2: YYCURSOR = YYMARKER;
|
||||
switch(yyaccept){
|
||||
case 0: goto yy4;
|
||||
}
|
||||
yy3: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy185;
|
||||
yy4:
|
||||
#line 99
|
||||
{ TAG_IMPLICIT( "str" ); }
|
||||
yy5: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'o') goto yy158;
|
||||
if(yych == 'u') goto yy188;
|
||||
goto yy4;
|
||||
yy6: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= 'U'){
|
||||
if(yych == 'O') goto yy158;
|
||||
if(yych <= 'T') goto yy4;
|
||||
goto yy181;
|
||||
} else {
|
||||
if(yych <= 'o'){
|
||||
if(yych <= 'n') goto yy4;
|
||||
goto yy158;
|
||||
} else {
|
||||
if(yych == 'u') goto yy182;
|
||||
goto yy4;
|
||||
}
|
||||
}
|
||||
yy7: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'r') goto yy179;
|
||||
goto yy4;
|
||||
yy8: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'R') goto yy175;
|
||||
if(yych == 'r') goto yy176;
|
||||
goto yy4;
|
||||
yy9: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'e') goto yy174;
|
||||
goto yy4;
|
||||
yy10: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'E') goto yy172;
|
||||
if(yych == 'e') goto yy173;
|
||||
goto yy4;
|
||||
yy11: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'f') goto yy171;
|
||||
if(yych == 'n') goto yy168;
|
||||
goto yy4;
|
||||
yy12: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= 'N'){
|
||||
if(yych == 'F') goto yy166;
|
||||
if(yych <= 'M') goto yy4;
|
||||
goto yy168;
|
||||
} else {
|
||||
if(yych <= 'f'){
|
||||
if(yych <= 'e') goto yy4;
|
||||
goto yy167;
|
||||
} else {
|
||||
if(yych == 'n') goto yy168;
|
||||
goto yy4;
|
||||
}
|
||||
}
|
||||
yy13: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'a') goto yy163;
|
||||
goto yy4;
|
||||
yy14: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych == 'A') goto yy154;
|
||||
if(yych == 'a') goto yy155;
|
||||
goto yy4;
|
||||
yy15: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= '/'){
|
||||
if(yych == '.') goto yy153;
|
||||
goto yy4;
|
||||
} else {
|
||||
if(yych <= '0') goto yy144;
|
||||
if(yych <= '9') goto yy38;
|
||||
goto yy4;
|
||||
}
|
||||
yy16: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= '/'){
|
||||
if(yych == '.') goto yy143;
|
||||
goto yy4;
|
||||
} else {
|
||||
if(yych <= '0') goto yy144;
|
||||
if(yych <= '9') goto yy38;
|
||||
goto yy4;
|
||||
}
|
||||
yy17: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= '.'){
|
||||
if(yych <= '+'){
|
||||
if(yych <= '\000') goto yy42;
|
||||
goto yy4;
|
||||
} else {
|
||||
if(yych <= ',') goto yy128;
|
||||
if(yych <= '-') goto yy4;
|
||||
goto yy40;
|
||||
}
|
||||
} else {
|
||||
if(yych <= '9'){
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych <= '7') goto yy126;
|
||||
goto yy127;
|
||||
} else {
|
||||
if(yych == 'x') goto yy130;
|
||||
goto yy4;
|
||||
}
|
||||
}
|
||||
yy18: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= '-'){
|
||||
if(yych <= '\000') goto yy42;
|
||||
if(yych == ',') goto yy38;
|
||||
goto yy4;
|
||||
} else {
|
||||
if(yych <= '.') goto yy40;
|
||||
if(yych <= '/') goto yy4;
|
||||
if(yych <= '9') goto yy37;
|
||||
goto yy4;
|
||||
}
|
||||
yy19: yyaccept = 0;
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if(yych <= 'N'){
|
||||
if(yych == 'I') goto yy24;
|
||||
if(yych <= 'M') goto yy4;
|
||||
goto yy22;
|
||||
} else {
|
||||
if(yych <= 'i'){
|
||||
if(yych <= 'h') goto yy4;
|
||||
goto yy23;
|
||||
} else {
|
||||
if(yych == 'n') goto yy21;
|
||||
goto yy4;
|
||||
}
|
||||
}
|
||||
yy20: yych = *++YYCURSOR;
|
||||
goto yy4;
|
||||
yy21: yych = *++YYCURSOR;
|
||||
if(yych == 'a') goto yy36;
|
||||
goto yy2;
|
||||
yy22: yych = *++YYCURSOR;
|
||||
if(yych == 'A') goto yy31;
|
||||
if(yych == 'a') goto yy32;
|
||||
goto yy2;
|
||||
yy23: yych = *++YYCURSOR;
|
||||
if(yych == 'n') goto yy30;
|
||||
goto yy2;
|
||||
yy24: yych = *++YYCURSOR;
|
||||
if(yych == 'N') goto yy25;
|
||||
if(yych == 'n') goto yy26;
|
||||
goto yy2;
|
||||
yy25: yych = *++YYCURSOR;
|
||||
if(yych == 'F') goto yy27;
|
||||
goto yy2;
|
||||
yy26: yych = *++YYCURSOR;
|
||||
if(yych != 'f') goto yy2;
|
||||
yy27: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy28: yych = *++YYCURSOR;
|
||||
yy29:
|
||||
#line 85
|
||||
{ TAG_IMPLICIT( "float#inf" ); }
|
||||
yy30: yych = *++YYCURSOR;
|
||||
if(yych == 'f') goto yy27;
|
||||
goto yy2;
|
||||
yy31: yych = *++YYCURSOR;
|
||||
if(yych == 'N') goto yy33;
|
||||
goto yy2;
|
||||
yy32: yych = *++YYCURSOR;
|
||||
if(yych != 'N') goto yy2;
|
||||
yy33: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy34: yych = *++YYCURSOR;
|
||||
yy35:
|
||||
#line 89
|
||||
{ TAG_IMPLICIT( "float#nan" ); }
|
||||
yy36: yych = *++YYCURSOR;
|
||||
if(yych == 'n') goto yy33;
|
||||
goto yy2;
|
||||
yy37: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy39;
|
||||
if(yych <= '9') goto yy56;
|
||||
goto yy39;
|
||||
yy38: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy39: if(yybm[0+yych] & 1) goto yy38;
|
||||
if(yych <= '\000') goto yy42;
|
||||
if(yych != '.') goto yy2;
|
||||
yy40: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy41: if(yybm[0+yych] & 2) goto yy40;
|
||||
if(yych <= '.'){
|
||||
if(yych <= '+'){
|
||||
if(yych <= '\000') goto yy46;
|
||||
goto yy2;
|
||||
} else {
|
||||
if(yych <= ',') goto yy44;
|
||||
if(yych <= '-') goto yy2;
|
||||
goto yy48;
|
||||
}
|
||||
} else {
|
||||
if(yych <= 'E'){
|
||||
if(yych <= 'D') goto yy2;
|
||||
goto yy50;
|
||||
} else {
|
||||
if(yych == 'e') goto yy50;
|
||||
goto yy2;
|
||||
}
|
||||
}
|
||||
yy42: yych = *++YYCURSOR;
|
||||
yy43:
|
||||
#line 79
|
||||
{ TAG_IMPLICIT( "int" ); }
|
||||
yy44: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy45: if(yych <= ','){
|
||||
if(yych <= '\000') goto yy46;
|
||||
if(yych <= '+') goto yy2;
|
||||
goto yy44;
|
||||
} else {
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy44;
|
||||
goto yy2;
|
||||
}
|
||||
yy46: yych = *++YYCURSOR;
|
||||
yy47:
|
||||
#line 81
|
||||
{ TAG_IMPLICIT( "float#fix" ); }
|
||||
yy48: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy49: if(yybm[0+yych] & 4) goto yy48;
|
||||
if(yych == 'E') goto yy50;
|
||||
if(yych != 'e') goto yy2;
|
||||
yy50: yych = *++YYCURSOR;
|
||||
if(yych == '+') goto yy51;
|
||||
if(yych != '-') goto yy2;
|
||||
yy51: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy2;
|
||||
goto yy53;
|
||||
yy52: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy53: if(yych <= '\000') goto yy54;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy52;
|
||||
goto yy2;
|
||||
yy54: yych = *++YYCURSOR;
|
||||
yy55:
|
||||
#line 83
|
||||
{ TAG_IMPLICIT( "float#exp" ); }
|
||||
yy56: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy39;
|
||||
if(yych >= ':') goto yy39;
|
||||
yy57: yych = *++YYCURSOR;
|
||||
if(yych != '-') goto yy39;
|
||||
yy58: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy59: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy60: yych = *++YYCURSOR;
|
||||
if(yych != '-') goto yy2;
|
||||
yy61: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy62: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy63: yych = *++YYCURSOR;
|
||||
if(yych <= 'S'){
|
||||
if(yych <= '\000') goto yy64;
|
||||
if(yych <= '/') goto yy69;
|
||||
if(yych <= '9') goto yy2;
|
||||
goto yy69;
|
||||
} else {
|
||||
if(yych <= 'T') goto yy66;
|
||||
if(yych == 't') goto yy67;
|
||||
goto yy69;
|
||||
}
|
||||
yy64: yych = *++YYCURSOR;
|
||||
yy65:
|
||||
#line 91
|
||||
{ TAG_IMPLICIT( "timestamp#ymd" ); }
|
||||
yy66: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy112;
|
||||
goto yy2;
|
||||
yy67: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy92;
|
||||
goto yy2;
|
||||
yy68: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy69: if(yybm[0+yych] & 8) goto yy68;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy70: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy71: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy72: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy73: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy74: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy75: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy76: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy77: yych = *++YYCURSOR;
|
||||
if(yych <= '\037'){
|
||||
if(yych == '\t') goto yy80;
|
||||
goto yy2;
|
||||
} else {
|
||||
if(yych <= ' ') goto yy80;
|
||||
if(yych != '.') goto yy2;
|
||||
}
|
||||
yy78: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy79: if(yybm[0+yych] & 16) goto yy78;
|
||||
if(yych <= '0') goto yy2;
|
||||
if(yych <= '9') goto yy90;
|
||||
goto yy2;
|
||||
yy80: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy81: if(yych <= '*'){
|
||||
if(yych <= '\t'){
|
||||
if(yych <= '\b') goto yy2;
|
||||
goto yy80;
|
||||
} else {
|
||||
if(yych == ' ') goto yy80;
|
||||
goto yy2;
|
||||
}
|
||||
} else {
|
||||
if(yych <= '-'){
|
||||
if(yych == ',') goto yy2;
|
||||
goto yy83;
|
||||
} else {
|
||||
if(yych != 'Z') goto yy2;
|
||||
}
|
||||
}
|
||||
yy82: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy87;
|
||||
goto yy2;
|
||||
yy83: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy84: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy85: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy87;
|
||||
if(yych != ':') goto yy2;
|
||||
yy86: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy89;
|
||||
goto yy2;
|
||||
yy87: yych = *++YYCURSOR;
|
||||
yy88:
|
||||
#line 95
|
||||
{ TAG_IMPLICIT( "timestamp#spaced" ); }
|
||||
yy89: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy82;
|
||||
goto yy2;
|
||||
yy90: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy91: if(yybm[0+yych] & 16) goto yy78;
|
||||
if(yych <= '\037'){
|
||||
if(yych == '\t') goto yy80;
|
||||
goto yy2;
|
||||
} else {
|
||||
if(yych <= ' ') goto yy80;
|
||||
if(yych <= '0') goto yy2;
|
||||
if(yych <= '9') goto yy90;
|
||||
goto yy2;
|
||||
}
|
||||
yy92: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy93: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy94: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy95: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy96: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy97: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy98: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy99: yych = *++YYCURSOR;
|
||||
if(yych <= '-'){
|
||||
if(yych == '+') goto yy103;
|
||||
if(yych <= ',') goto yy2;
|
||||
goto yy103;
|
||||
} else {
|
||||
if(yych <= '.') goto yy100;
|
||||
if(yych == 'Z') goto yy102;
|
||||
goto yy2;
|
||||
}
|
||||
yy100: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy101: if(yych <= '/') goto yy2;
|
||||
if(yych <= '0') goto yy100;
|
||||
if(yych <= '9') goto yy110;
|
||||
goto yy2;
|
||||
yy102: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy107;
|
||||
goto yy2;
|
||||
yy103: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy104: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy105: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy107;
|
||||
if(yych != ':') goto yy2;
|
||||
yy106: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy109;
|
||||
goto yy2;
|
||||
yy107: yych = *++YYCURSOR;
|
||||
yy108:
|
||||
#line 93
|
||||
{ TAG_IMPLICIT( "timestamp#iso8601" ); }
|
||||
yy109: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy102;
|
||||
goto yy2;
|
||||
yy110: ++YYCURSOR;
|
||||
if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
|
||||
yych = *YYCURSOR;
|
||||
yy111: if(yych <= '/'){
|
||||
if(yych <= '+'){
|
||||
if(yych <= '*') goto yy2;
|
||||
goto yy103;
|
||||
} else {
|
||||
if(yych == '-') goto yy103;
|
||||
goto yy2;
|
||||
}
|
||||
} else {
|
||||
if(yych <= '9'){
|
||||
if(yych <= '0') goto yy100;
|
||||
goto yy110;
|
||||
} else {
|
||||
if(yych == 'Z') goto yy102;
|
||||
goto yy2;
|
||||
}
|
||||
}
|
||||
yy112: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy113: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy114: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy115: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy116: yych = *++YYCURSOR;
|
||||
if(yych != ':') goto yy2;
|
||||
yy117: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy118: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych >= ':') goto yy2;
|
||||
yy119: yych = *++YYCURSOR;
|
||||
if(yych <= '-'){
|
||||
if(yych == '+') goto yy103;
|
||||
if(yych <= ',') goto yy2;
|
||||
goto yy103;
|
||||
} else {
|
||||
if(yych <= '.') goto yy120;
|
||||
if(yych == 'Z') goto yy122;
|
||||
goto yy2;
|
||||
}
|
||||
yy120: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy121: if(yych <= '/') goto yy2;
|
||||
if(yych <= '0') goto yy120;
|
||||
if(yych <= '9') goto yy124;
|
||||
goto yy2;
|
||||
yy122: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy123: yych = *++YYCURSOR;
|
||||
goto yy108;
|
||||
yy124: ++YYCURSOR;
|
||||
if((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
|
||||
yych = *YYCURSOR;
|
||||
yy125: if(yych <= '/'){
|
||||
if(yych <= '+'){
|
||||
if(yych <= '*') goto yy2;
|
||||
goto yy103;
|
||||
} else {
|
||||
if(yych == '-') goto yy103;
|
||||
goto yy2;
|
||||
}
|
||||
} else {
|
||||
if(yych <= '9'){
|
||||
if(yych <= '0') goto yy120;
|
||||
goto yy124;
|
||||
} else {
|
||||
if(yych == 'Z') goto yy122;
|
||||
goto yy2;
|
||||
}
|
||||
}
|
||||
yy126: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy129;
|
||||
if(yych <= '7') goto yy141;
|
||||
if(yych <= '9') goto yy139;
|
||||
goto yy129;
|
||||
yy127: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy138;
|
||||
if(yych <= '9') goto yy139;
|
||||
goto yy138;
|
||||
yy128: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy129: if(yybm[0+yych] & 64) goto yy128;
|
||||
if(yych <= '.'){
|
||||
if(yych <= '\000') goto yy135;
|
||||
if(yych <= '-') goto yy2;
|
||||
goto yy40;
|
||||
} else {
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy137;
|
||||
goto yy2;
|
||||
}
|
||||
yy130: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy2;
|
||||
goto yy132;
|
||||
yy131: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy132: if(yybm[0+yych] & 128) goto yy131;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy133: yych = *++YYCURSOR;
|
||||
yy134:
|
||||
#line 75
|
||||
{ TAG_IMPLICIT( "int#hex" ); }
|
||||
yy135: yych = *++YYCURSOR;
|
||||
yy136:
|
||||
#line 77
|
||||
{ TAG_IMPLICIT( "int#oct" ); }
|
||||
yy137: ++YYCURSOR;
|
||||
if(YYLIMIT == YYCURSOR) YYFILL(1);
|
||||
yych = *YYCURSOR;
|
||||
yy138: if(yych <= '-'){
|
||||
if(yych == ',') goto yy137;
|
||||
goto yy2;
|
||||
} else {
|
||||
if(yych <= '.') goto yy40;
|
||||
if(yych <= '/') goto yy2;
|
||||
if(yych <= '9') goto yy137;
|
||||
goto yy2;
|
||||
}
|
||||
yy139: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy138;
|
||||
if(yych >= ':') goto yy138;
|
||||
yy140: yych = *++YYCURSOR;
|
||||
if(yych == '-') goto yy58;
|
||||
goto yy138;
|
||||
yy141: yych = *++YYCURSOR;
|
||||
if(yych <= '/') goto yy129;
|
||||
if(yych <= '7') goto yy142;
|
||||
if(yych <= '9') goto yy140;
|
||||
goto yy129;
|
||||
yy142: yych = *++YYCURSOR;
|
||||
if(yych == '-') goto yy58;
|
||||
goto yy129;
|
||||
yy143: yych = *++YYCURSOR;
|
||||
if(yych == 'I') goto yy146;
|
||||
if(yych == 'i') goto yy145;
|
||||
goto yy2;
|
||||
yy144: yych = *++YYCURSOR;
|
||||
if(yych <= '\000') goto yy42;
|
||||
if(yych == 'x') goto yy130;
|
||||
goto yy129;
|
||||
yy145: yych = *++YYCURSOR;
|
||||
if(yych == 'n') goto yy152;
|
||||
goto yy2;
|
||||
yy146: yych = *++YYCURSOR;
|
||||
if(yych == 'N') goto yy147;
|
||||
if(yych == 'n') goto yy148;
|
||||
goto yy2;
|
||||
yy147: yych = *++YYCURSOR;
|
||||
if(yych == 'F') goto yy149;
|
||||
goto yy2;
|
||||
yy148: yych = *++YYCURSOR;
|
||||
if(yych != 'f') goto yy2;
|
||||
yy149: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy150: yych = *++YYCURSOR;
|
||||
yy151:
|
||||
#line 87
|
||||
{ TAG_IMPLICIT( "float#neginf" ); }
|
||||
yy152: yych = *++YYCURSOR;
|
||||
if(yych == 'f') goto yy149;
|
||||
goto yy2;
|
||||
yy153: yych = *++YYCURSOR;
|
||||
if(yych == 'I') goto yy24;
|
||||
if(yych == 'i') goto yy23;
|
||||
goto yy2;
|
||||
yy154: yych = *++YYCURSOR;
|
||||
if(yych == 'L') goto yy161;
|
||||
goto yy2;
|
||||
yy155: yych = *++YYCURSOR;
|
||||
if(yych != 'l') goto yy2;
|
||||
yy156: yych = *++YYCURSOR;
|
||||
if(yych != 's') goto yy2;
|
||||
yy157: yych = *++YYCURSOR;
|
||||
if(yych != 'e') goto yy2;
|
||||
yy158: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy159: yych = *++YYCURSOR;
|
||||
yy160:
|
||||
#line 73
|
||||
{ TAG_IMPLICIT( "bool#no" ); }
|
||||
yy161: yych = *++YYCURSOR;
|
||||
if(yych != 'S') goto yy2;
|
||||
yy162: yych = *++YYCURSOR;
|
||||
if(yych == 'E') goto yy158;
|
||||
goto yy2;
|
||||
yy163: yych = *++YYCURSOR;
|
||||
if(yych != 'l') goto yy2;
|
||||
yy164: yych = *++YYCURSOR;
|
||||
if(yych != 's') goto yy2;
|
||||
yy165: yych = *++YYCURSOR;
|
||||
if(yych == 'e') goto yy158;
|
||||
goto yy2;
|
||||
yy166: yych = *++YYCURSOR;
|
||||
if(yych == 'F') goto yy158;
|
||||
goto yy2;
|
||||
yy167: yych = *++YYCURSOR;
|
||||
if(yych == 'f') goto yy158;
|
||||
goto yy2;
|
||||
yy168: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy169: yych = *++YYCURSOR;
|
||||
yy170:
|
||||
#line 71
|
||||
{ TAG_IMPLICIT( "bool#yes" ); }
|
||||
yy171: yych = *++YYCURSOR;
|
||||
if(yych == 'f') goto yy158;
|
||||
goto yy2;
|
||||
yy172: yych = *++YYCURSOR;
|
||||
if(yych == 'S') goto yy168;
|
||||
goto yy2;
|
||||
yy173: yych = *++YYCURSOR;
|
||||
if(yych == 's') goto yy168;
|
||||
goto yy2;
|
||||
yy174: yych = *++YYCURSOR;
|
||||
if(yych == 's') goto yy168;
|
||||
goto yy2;
|
||||
yy175: yych = *++YYCURSOR;
|
||||
if(yych == 'U') goto yy178;
|
||||
goto yy2;
|
||||
yy176: yych = *++YYCURSOR;
|
||||
if(yych != 'u') goto yy2;
|
||||
yy177: yych = *++YYCURSOR;
|
||||
if(yych == 'e') goto yy168;
|
||||
goto yy2;
|
||||
yy178: yych = *++YYCURSOR;
|
||||
if(yych == 'E') goto yy168;
|
||||
goto yy2;
|
||||
yy179: yych = *++YYCURSOR;
|
||||
if(yych != 'u') goto yy2;
|
||||
yy180: yych = *++YYCURSOR;
|
||||
if(yych == 'e') goto yy168;
|
||||
goto yy2;
|
||||
yy181: yych = *++YYCURSOR;
|
||||
if(yych == 'L') goto yy187;
|
||||
goto yy2;
|
||||
yy182: yych = *++YYCURSOR;
|
||||
if(yych != 'l') goto yy2;
|
||||
yy183: yych = *++YYCURSOR;
|
||||
if(yych != 'l') goto yy2;
|
||||
yy184: yych = *++YYCURSOR;
|
||||
if(yych >= '\001') goto yy2;
|
||||
yy185: yych = *++YYCURSOR;
|
||||
yy186:
|
||||
#line 69
|
||||
{ TAG_IMPLICIT( "null" ); }
|
||||
yy187: yych = *++YYCURSOR;
|
||||
if(yych == 'L') goto yy184;
|
||||
goto yy2;
|
||||
yy188: yych = *++YYCURSOR;
|
||||
if(yych != 'l') goto yy2;
|
||||
yy189: yych = *++YYCURSOR;
|
||||
if(yych == 'l') goto yy184;
|
||||
goto yy2;
|
||||
}
|
||||
#line 101
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
//
|
||||
// node.c
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
|
||||
#include "syck.h"
|
||||
|
||||
//
|
||||
// Node allocation functions
|
||||
//
|
||||
SyckNode *
|
||||
syck_alloc_node( enum syck_kind_tag type )
|
||||
{
|
||||
SyckNode *s;
|
||||
|
||||
s = S_ALLOC( SyckNode );
|
||||
s->kind = type;
|
||||
s->id = NULL;
|
||||
s->type_id = NULL;
|
||||
s->anchor = NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
syck_free_node( SyckNode *n )
|
||||
{
|
||||
syck_free_members( n );
|
||||
if ( n->type_id != NULL )
|
||||
S_FREE( n->type_id );
|
||||
if ( n->anchor != NULL )
|
||||
S_FREE( n->anchor );
|
||||
S_FREE( n );
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_alloc_map()
|
||||
{
|
||||
SyckNode *n;
|
||||
struct SyckMap *m;
|
||||
|
||||
m = S_ALLOC( struct SyckMap );
|
||||
m->idx = 0;
|
||||
m->capa = ALLOC_CT;
|
||||
m->keys = S_ALLOC_N( SYMID, m->capa );
|
||||
m->values = S_ALLOC_N( SYMID, m->capa );
|
||||
|
||||
n = syck_alloc_node( syck_map_kind );
|
||||
n->data.pairs = m;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_alloc_seq()
|
||||
{
|
||||
SyckNode *n;
|
||||
struct SyckSeq *s;
|
||||
|
||||
s = S_ALLOC( struct SyckSeq );
|
||||
s->idx = 0;
|
||||
s->capa = ALLOC_CT;
|
||||
s->items = S_ALLOC_N( SYMID, s->capa );
|
||||
|
||||
n = syck_alloc_node( syck_seq_kind );
|
||||
n->data.list = s;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_alloc_str()
|
||||
{
|
||||
SyckNode *n;
|
||||
struct SyckStr *s;
|
||||
|
||||
s = S_ALLOC( struct SyckStr );
|
||||
s->len = 0;
|
||||
s->ptr = NULL;
|
||||
|
||||
n = syck_alloc_node( syck_str_kind );
|
||||
n->data.str = s;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_new_str( char *str )
|
||||
{
|
||||
return syck_new_str2( str, strlen( str ) );
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_new_str2( char *str, long len )
|
||||
{
|
||||
SyckNode *n;
|
||||
|
||||
n = syck_alloc_str();
|
||||
n->data.str->ptr = S_ALLOC_N( char, len + 1 );
|
||||
n->data.str->len = len;
|
||||
memcpy( n->data.str->ptr, str, len );
|
||||
n->data.str->ptr[len] = '\0';
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
syck_str_blow_away_commas( SyckNode *n )
|
||||
{
|
||||
char *go, *end;
|
||||
|
||||
go = n->data.str->ptr;
|
||||
end = go + n->data.str->len;
|
||||
while ( *(++go) != '\0' )
|
||||
{
|
||||
if ( *go == ',' )
|
||||
{
|
||||
n->data.str->len -= 1;
|
||||
memmove( go, go + 1, end - go );
|
||||
end -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
syck_str_read( SyckNode *n )
|
||||
{
|
||||
ASSERT( n != NULL );
|
||||
return n->data.str->ptr;
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_new_map( SYMID key, SYMID value )
|
||||
{
|
||||
SyckNode *n;
|
||||
|
||||
n = syck_alloc_map();
|
||||
syck_map_add( n, key, value );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
syck_map_add( SyckNode *map, SYMID key, SYMID value )
|
||||
{
|
||||
struct SyckMap *m;
|
||||
long idx;
|
||||
|
||||
ASSERT( map != NULL );
|
||||
ASSERT( map->data.pairs != NULL );
|
||||
|
||||
m = map->data.pairs;
|
||||
idx = m->idx;
|
||||
m->idx += 1;
|
||||
if ( m->idx > m->capa )
|
||||
{
|
||||
m->capa += ALLOC_CT;
|
||||
S_REALLOC_N( m->keys, SYMID, m->capa );
|
||||
S_REALLOC_N( m->values, SYMID, m->capa );
|
||||
}
|
||||
m->keys[idx] = key;
|
||||
m->values[idx] = value;
|
||||
}
|
||||
|
||||
void
|
||||
syck_map_update( SyckNode *map1, SyckNode *map2 )
|
||||
{
|
||||
struct SyckMap *m1, *m2;
|
||||
long new_idx, new_capa;
|
||||
ASSERT( map1 != NULL );
|
||||
ASSERT( map2 != NULL );
|
||||
|
||||
m1 = map1->data.pairs;
|
||||
m2 = map2->data.pairs;
|
||||
if ( m2->idx < 1 ) return;
|
||||
|
||||
new_idx = m1->idx;
|
||||
new_idx += m2->idx;
|
||||
new_capa = m1->capa;
|
||||
while ( new_idx > new_capa )
|
||||
{
|
||||
new_capa += ALLOC_CT;
|
||||
}
|
||||
if ( new_capa > m1->capa )
|
||||
{
|
||||
m1->capa = new_capa;
|
||||
S_REALLOC_N( m1->keys, SYMID, m1->capa );
|
||||
S_REALLOC_N( m1->values, SYMID, m1->capa );
|
||||
}
|
||||
new_idx = 0;
|
||||
for ( new_idx = 0; new_idx < m2->idx; m1->idx++, new_idx++ )
|
||||
{
|
||||
m1->keys[m1->idx] = m2->keys[new_idx];
|
||||
m1->values[m1->idx] = m2->values[new_idx];
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
syck_map_count( SyckNode *map )
|
||||
{
|
||||
ASSERT( map != NULL );
|
||||
ASSERT( map->data.pairs != NULL );
|
||||
return map->data.pairs->idx;
|
||||
}
|
||||
|
||||
SYMID
|
||||
syck_map_read( SyckNode *map, enum map_part p, long idx )
|
||||
{
|
||||
struct SyckMap *m;
|
||||
|
||||
ASSERT( map != NULL );
|
||||
m = map->data.pairs;
|
||||
ASSERT( m != NULL );
|
||||
if ( p == map_key )
|
||||
{
|
||||
return m->keys[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
return m->values[idx];
|
||||
}
|
||||
}
|
||||
|
||||
SyckNode *
|
||||
syck_new_seq( SYMID value )
|
||||
{
|
||||
SyckNode *n;
|
||||
|
||||
n = syck_alloc_seq();
|
||||
syck_seq_add( n, value );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
syck_seq_add( SyckNode *arr, SYMID value )
|
||||
{
|
||||
struct SyckSeq *s;
|
||||
long idx;
|
||||
|
||||
ASSERT( arr != NULL );
|
||||
ASSERT( arr->data.list != NULL );
|
||||
|
||||
s = arr->data.list;
|
||||
idx = s->idx;
|
||||
s->idx += 1;
|
||||
if ( s->idx > s->capa )
|
||||
{
|
||||
s->capa += ALLOC_CT;
|
||||
S_REALLOC_N( s->items, SYMID, s->capa );
|
||||
}
|
||||
s->items[idx] = value;
|
||||
}
|
||||
|
||||
long
|
||||
syck_seq_count( SyckNode *seq )
|
||||
{
|
||||
ASSERT( seq != NULL );
|
||||
ASSERT( seq->data.list != NULL );
|
||||
return seq->data.list->idx;
|
||||
}
|
||||
|
||||
SYMID
|
||||
syck_seq_read( SyckNode *seq, long idx )
|
||||
{
|
||||
struct SyckSeq *s;
|
||||
|
||||
ASSERT( seq != NULL );
|
||||
s = seq->data.list;
|
||||
ASSERT( s != NULL );
|
||||
return s->items[idx];
|
||||
}
|
||||
|
||||
void
|
||||
syck_free_members( SyckNode *n )
|
||||
{
|
||||
int i;
|
||||
switch ( n->kind )
|
||||
{
|
||||
case syck_str_kind:
|
||||
if ( n->data.str->ptr != NULL )
|
||||
{
|
||||
S_FREE( n->data.str->ptr );
|
||||
n->data.str->ptr = NULL;
|
||||
n->data.str->len = 0;
|
||||
S_FREE( n->data.str );
|
||||
}
|
||||
break;
|
||||
|
||||
case syck_seq_kind:
|
||||
S_FREE( n->data.list->items );
|
||||
S_FREE( n->data.list );
|
||||
break;
|
||||
|
||||
case syck_map_kind:
|
||||
S_FREE( n->data.pairs->keys );
|
||||
S_FREE( n->data.pairs->values );
|
||||
S_FREE( n->data.pairs );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,569 @@
|
|||
//
|
||||
// rubyext.c
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
|
||||
#include "ruby.h"
|
||||
#include "syck.h"
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
static ID s_utc, s_read, s_binmode;
|
||||
static VALUE sym_model, sym_generic;
|
||||
static VALUE sym_scalar, sym_seq, sym_map;
|
||||
VALUE cNode;
|
||||
|
||||
//
|
||||
// my private collection of numerical oddities.
|
||||
//
|
||||
static double S_zero() { return 0.0; }
|
||||
static double S_one() { return 1.0; }
|
||||
static double S_inf() { return S_one() / S_zero(); }
|
||||
static double S_nan() { return S_zero() / S_zero(); }
|
||||
|
||||
static VALUE syck_node_transform( VALUE );
|
||||
|
||||
//
|
||||
// read from io.
|
||||
//
|
||||
long
|
||||
rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
|
||||
{
|
||||
long len = 0;
|
||||
|
||||
ASSERT( str != NULL );
|
||||
max_size -= skip;
|
||||
if ( max_size < 0 ) max_size = 0;
|
||||
|
||||
if ( max_size > 0 )
|
||||
{
|
||||
//
|
||||
// call io#read.
|
||||
//
|
||||
VALUE src = (VALUE)str->ptr;
|
||||
VALUE n = LONG2NUM(max_size);
|
||||
VALUE str = rb_funcall2(src, s_read, 1, &n);
|
||||
if (!NIL_P(str))
|
||||
{
|
||||
len = RSTRING(str)->len;
|
||||
memcpy( buf + skip, RSTRING(str)->ptr, len );
|
||||
}
|
||||
}
|
||||
len += skip;
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
//
|
||||
// determine: are we reading from a string or io?
|
||||
//
|
||||
void
|
||||
syck_parser_assign_io(parser, port)
|
||||
SyckParser *parser;
|
||||
VALUE port;
|
||||
{
|
||||
if (rb_respond_to(port, rb_intern("to_str"))) {
|
||||
//arg.taint = OBJ_TAINTED(port); /* original taintedness */
|
||||
//StringValue(port); /* possible conversion */
|
||||
syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
|
||||
}
|
||||
else if (rb_respond_to(port, s_read)) {
|
||||
if (rb_respond_to(port, s_binmode)) {
|
||||
rb_funcall2(port, s_binmode, 0, 0);
|
||||
}
|
||||
//arg.taint = Qfalse;
|
||||
syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eTypeError, "instance of IO needed");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// creating timestamps
|
||||
//
|
||||
SYMID
|
||||
rb_syck_mktime(str)
|
||||
char *str;
|
||||
{
|
||||
VALUE time;
|
||||
char *ptr = str;
|
||||
VALUE year, mon, day, hour, min, sec;
|
||||
|
||||
// Year
|
||||
ptr[4] = '\0';
|
||||
year = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
// Month
|
||||
ptr += 4;
|
||||
while ( !isdigit( *ptr ) ) ptr++;
|
||||
mon = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
// Day
|
||||
ptr += 2;
|
||||
while ( !isdigit( *ptr ) ) ptr++;
|
||||
day = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
// Hour
|
||||
ptr += 2;
|
||||
while ( !isdigit( *ptr ) ) ptr++;
|
||||
hour = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
// Minute
|
||||
ptr += 2;
|
||||
while ( !isdigit( *ptr ) ) ptr++;
|
||||
min = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
// Second
|
||||
ptr += 2;
|
||||
while ( !isdigit( *ptr ) ) ptr++;
|
||||
sec = INT2FIX(strtol(ptr, NULL, 10));
|
||||
|
||||
time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec );
|
||||
return time;
|
||||
}
|
||||
|
||||
//
|
||||
// {generic mode} node handler
|
||||
// - Loads data into Node classes
|
||||
//
|
||||
SYMID
|
||||
rb_syck_parse_handler(p, n)
|
||||
SyckParser *p;
|
||||
SyckNode *n;
|
||||
{
|
||||
VALUE t, v, obj;
|
||||
int i;
|
||||
|
||||
obj = rb_obj_alloc(cNode);
|
||||
if ( n->type_id != NULL )
|
||||
{
|
||||
t = rb_str_new2(n->type_id);
|
||||
rb_iv_set(obj, "@type_id", t);
|
||||
}
|
||||
|
||||
switch (n->kind)
|
||||
{
|
||||
case syck_str_kind:
|
||||
rb_iv_set(obj, "@kind", sym_scalar);
|
||||
v = rb_str_new( n->data.str->ptr, n->data.str->len );
|
||||
break;
|
||||
|
||||
case syck_seq_kind:
|
||||
rb_iv_set(obj, "@kind", sym_seq);
|
||||
v = rb_ary_new2( n->data.list->idx );
|
||||
for ( i = 0; i < n->data.list->idx; i++ )
|
||||
{
|
||||
rb_ary_store( v, i, syck_seq_read( n, i ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case syck_map_kind:
|
||||
rb_iv_set(obj, "@kind", sym_map);
|
||||
v = rb_hash_new();
|
||||
for ( i = 0; i < n->data.pairs->idx; i++ )
|
||||
{
|
||||
VALUE key = syck_node_transform( syck_map_read( n, map_key, i ) );
|
||||
VALUE val = rb_ary_new();
|
||||
rb_ary_push(val, syck_map_read( n, map_key, i ));
|
||||
rb_ary_push(val, syck_map_read( n, map_value, i ));
|
||||
|
||||
rb_hash_aset( v, key, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( p->bonus != 0 )
|
||||
{
|
||||
VALUE proc = (VALUE)p->bonus;
|
||||
rb_funcall(proc, rb_intern("call"), 1, v);
|
||||
}
|
||||
rb_iv_set(obj, "@value", v);
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// {native mode} node handler
|
||||
// - Converts data into native Ruby types
|
||||
//
|
||||
SYMID
|
||||
rb_syck_load_handler(p, n)
|
||||
SyckParser *p;
|
||||
SyckNode *n;
|
||||
{
|
||||
VALUE obj;
|
||||
long i;
|
||||
int str = 0;
|
||||
|
||||
switch (n->kind)
|
||||
{
|
||||
case syck_str_kind:
|
||||
if ( n->type_id == NULL || strcmp( n->type_id, "str" ) == 0 )
|
||||
{
|
||||
obj = rb_str_new( n->data.str->ptr, n->data.str->len );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "null" ) == 0 )
|
||||
{
|
||||
obj = Qnil;
|
||||
}
|
||||
else if ( strcmp( n->type_id, "bool#yes" ) == 0 )
|
||||
{
|
||||
obj = Qtrue;
|
||||
}
|
||||
else if ( strcmp( n->type_id, "bool#no" ) == 0 )
|
||||
{
|
||||
obj = Qfalse;
|
||||
}
|
||||
else if ( strcmp( n->type_id, "int#hex" ) == 0 )
|
||||
{
|
||||
obj = rb_cstr2inum( n->data.str->ptr, 16 );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "int#oct" ) == 0 )
|
||||
{
|
||||
obj = rb_cstr2inum( n->data.str->ptr, 8 );
|
||||
}
|
||||
else if ( strncmp( n->type_id, "int", 3 ) == 0 )
|
||||
{
|
||||
syck_str_blow_away_commas( n );
|
||||
obj = rb_cstr2inum( n->data.str->ptr, 10 );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "float#nan" ) == 0 )
|
||||
{
|
||||
obj = rb_float_new( S_nan() );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "float#inf" ) == 0 )
|
||||
{
|
||||
obj = rb_float_new( S_inf() );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "float#neginf" ) == 0 )
|
||||
{
|
||||
obj = rb_float_new( -S_inf() );
|
||||
}
|
||||
else if ( strncmp( n->type_id, "float", 5 ) == 0 )
|
||||
{
|
||||
double f;
|
||||
syck_str_blow_away_commas( n );
|
||||
f = strtod( n->data.str->ptr, NULL );
|
||||
obj = rb_float_new( f );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "timestamp#iso8601" ) == 0 )
|
||||
{
|
||||
obj = rb_syck_mktime( n->data.str->ptr );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "timestamp#spaced" ) == 0 )
|
||||
{
|
||||
obj = rb_syck_mktime( n->data.str->ptr );
|
||||
}
|
||||
else if ( strcmp( n->type_id, "timestamp#ymd" ) == 0 )
|
||||
{
|
||||
S_REALLOC_N( n->data.str->ptr, char, 22 );
|
||||
strcat( n->data.str->ptr, "t12:00:00Z" );
|
||||
obj = rb_syck_mktime( n->data.str->ptr );
|
||||
}
|
||||
else if ( strncmp( n->type_id, "timestamp", 9 ) == 0 )
|
||||
{
|
||||
obj = rb_syck_mktime( n->data.str->ptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = rb_str_new( n->data.str->ptr, n->data.str->len );
|
||||
}
|
||||
break;
|
||||
|
||||
case syck_seq_kind:
|
||||
obj = rb_ary_new2( n->data.list->idx );
|
||||
for ( i = 0; i < n->data.list->idx; i++ )
|
||||
{
|
||||
rb_ary_store( obj, i, syck_seq_read( n, i ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case syck_map_kind:
|
||||
obj = rb_hash_new();
|
||||
for ( i = 0; i < n->data.pairs->idx; i++ )
|
||||
{
|
||||
rb_hash_aset( obj, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( p->bonus != 0 )
|
||||
{
|
||||
VALUE proc = (VALUE)p->bonus;
|
||||
rb_funcall(proc, rb_intern("call"), 1, obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// friendly errors.
|
||||
//
|
||||
void
|
||||
rb_syck_err_handler(p, msg)
|
||||
SyckParser *p;
|
||||
char *msg;
|
||||
{
|
||||
char *endl = p->cursor;
|
||||
|
||||
while ( *endl != '\0' && *endl != '\n' )
|
||||
endl++;
|
||||
|
||||
endl[0] = '\0';
|
||||
rb_raise(rb_eLoadError, "%s on line %d, col %d: `%s'",
|
||||
msg,
|
||||
p->linect,
|
||||
p->cursor - p->lineptr,
|
||||
p->lineptr);
|
||||
}
|
||||
|
||||
//
|
||||
// data loaded based on the model requested.
|
||||
//
|
||||
void
|
||||
syck_set_model( parser, model )
|
||||
SyckParser *parser;
|
||||
VALUE model;
|
||||
{
|
||||
if ( model == sym_generic )
|
||||
{
|
||||
syck_parser_handler( parser, rb_syck_parse_handler );
|
||||
syck_parser_error_handler( parser, rb_syck_err_handler );
|
||||
syck_parser_implicit_typing( parser, 1 );
|
||||
syck_parser_taguri_expansion( parser, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
syck_parser_handler( parser, rb_syck_load_handler );
|
||||
syck_parser_error_handler( parser, rb_syck_err_handler );
|
||||
syck_parser_implicit_typing( parser, 1 );
|
||||
syck_parser_taguri_expansion( parser, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// wrap syck_parse().
|
||||
//
|
||||
static VALUE
|
||||
rb_run_syck_parse(parser)
|
||||
SyckParser *parser;
|
||||
{
|
||||
return syck_parse(parser);
|
||||
}
|
||||
|
||||
//
|
||||
// free parser.
|
||||
//
|
||||
static VALUE
|
||||
rb_syck_ensure(parser)
|
||||
SyckParser *parser;
|
||||
{
|
||||
syck_free_parser( parser );
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Parser.new
|
||||
//
|
||||
VALUE
|
||||
syck_parser_new(argc, argv, class)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE class;
|
||||
{
|
||||
VALUE pobj, options, init_argv[1];
|
||||
SyckParser *parser = syck_new_parser();
|
||||
|
||||
rb_scan_args(argc, argv, "01", &options);
|
||||
pobj = Data_Wrap_Struct( class, 0, syck_free_parser, parser );
|
||||
|
||||
if ( ! rb_obj_is_instance_of( options, rb_cHash ) )
|
||||
{
|
||||
options = rb_hash_new();
|
||||
}
|
||||
init_argv[0] = options;
|
||||
rb_obj_call_init(pobj, 1, init_argv);
|
||||
return pobj;
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Parser.initialize( options )
|
||||
//
|
||||
static VALUE
|
||||
syck_parser_initialize( self, options )
|
||||
VALUE self, options;
|
||||
{
|
||||
rb_iv_set(self, "@options", options);
|
||||
return self;
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Parser.load( IO or String )
|
||||
//
|
||||
VALUE
|
||||
syck_parser_load(argc, argv, self)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE self;
|
||||
{
|
||||
VALUE port, proc, v, model;
|
||||
SyckParser *parser;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &port, &proc);
|
||||
Data_Get_Struct(self, SyckParser, parser);
|
||||
syck_parser_assign_io(parser, port);
|
||||
|
||||
model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
|
||||
syck_set_model( parser, model );
|
||||
|
||||
parser->bonus = 0;
|
||||
if ( !NIL_P( proc ) )
|
||||
{
|
||||
parser->bonus = (void *)proc;
|
||||
}
|
||||
|
||||
v = syck_parse( parser );
|
||||
if ( v == NULL )
|
||||
{
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
//v = rb_ensure(rb_run_syck_parse, (VALUE)&parser, rb_syck_ensure, (VALUE)&parser);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Parser.load_documents( IO or String ) { |doc| }
|
||||
//
|
||||
VALUE
|
||||
syck_parser_load_documents(argc, argv, self)
|
||||
int argc;
|
||||
VALUE *argv;
|
||||
VALUE self;
|
||||
{
|
||||
VALUE port, proc, v, model;
|
||||
SyckParser *parser;
|
||||
|
||||
rb_scan_args(argc, argv, "1&", &port, &proc);
|
||||
Data_Get_Struct(self, SyckParser, parser);
|
||||
syck_parser_assign_io(parser, port);
|
||||
|
||||
model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
|
||||
syck_set_model( parser, model );
|
||||
parser->bonus = 0;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
v = syck_parse( parser );
|
||||
if ( parser->eof == 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
rb_funcall( proc, rb_intern("call"), 1, v );
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Node.initialize
|
||||
//
|
||||
static VALUE
|
||||
syck_node_initialize( self, type_id, val )
|
||||
VALUE self, type_id, val;
|
||||
{
|
||||
rb_iv_set( self, "@type_id", type_id );
|
||||
rb_iv_set( self, "@value", val );
|
||||
}
|
||||
|
||||
static VALUE
|
||||
syck_node_thash( entry, t )
|
||||
VALUE entry, t;
|
||||
{
|
||||
VALUE key, val;
|
||||
key = rb_ary_entry( entry, 0 );
|
||||
val = syck_node_transform( rb_ary_entry( rb_ary_entry( entry, 1 ), 1 ) );
|
||||
rb_hash_aset( t, key, val );
|
||||
}
|
||||
|
||||
static VALUE
|
||||
syck_node_ahash( entry, t )
|
||||
VALUE entry, t;
|
||||
{
|
||||
VALUE val = syck_node_transform( entry );
|
||||
rb_ary_push( t, val );
|
||||
}
|
||||
|
||||
//
|
||||
// YAML::Syck::Node.transform
|
||||
//
|
||||
static VALUE
|
||||
syck_node_transform( self )
|
||||
VALUE self;
|
||||
{
|
||||
VALUE t = Qnil;
|
||||
VALUE val = rb_iv_get( self, "@value" );
|
||||
if ( rb_obj_is_instance_of( val, rb_cHash ) )
|
||||
{
|
||||
t = rb_hash_new();
|
||||
rb_iterate( rb_each, val, syck_node_thash, t );
|
||||
}
|
||||
else if ( rb_obj_is_instance_of( val, rb_cArray ) )
|
||||
{
|
||||
t = rb_ary_new();
|
||||
rb_iterate( rb_each, val, syck_node_ahash, t );
|
||||
}
|
||||
else
|
||||
{
|
||||
t = val;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize Syck extension
|
||||
//
|
||||
void
|
||||
Init_syck()
|
||||
{
|
||||
VALUE rb_yaml = rb_define_module( "YAML" );
|
||||
VALUE rb_syck = rb_define_module_under( rb_yaml, "Syck" );
|
||||
VALUE cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
|
||||
rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
|
||||
|
||||
//
|
||||
// Global symbols
|
||||
//
|
||||
s_utc = rb_intern("utc");
|
||||
s_read = rb_intern("read");
|
||||
s_binmode = rb_intern("binmode");
|
||||
sym_model = ID2SYM(rb_intern("Model"));
|
||||
sym_generic = ID2SYM(rb_intern("Generic"));
|
||||
sym_map = ID2SYM(rb_intern("map"));
|
||||
sym_scalar = ID2SYM(rb_intern("scalar"));
|
||||
sym_seq = ID2SYM(rb_intern("seq"));
|
||||
|
||||
//
|
||||
// Define YAML::Syck::Parser class
|
||||
//
|
||||
rb_define_attr( cParser, "options", 1, 1 );
|
||||
rb_define_singleton_method(cParser, "new", syck_parser_new, -1);
|
||||
rb_define_method(cParser, "initialize", syck_parser_initialize, 1);
|
||||
rb_define_method(cParser, "load", syck_parser_load, -1);
|
||||
rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
|
||||
|
||||
//
|
||||
// Define YAML::Syck::Node class
|
||||
//
|
||||
cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
|
||||
rb_define_attr( cNode, "kind", 1, 1 );
|
||||
rb_define_attr( cNode, "type_id", 1, 1 );
|
||||
rb_define_attr( cNode, "value", 1, 1 );
|
||||
rb_define_attr( cNode, "anchor", 1, 1 );
|
||||
rb_define_method( cNode, "initialize", syck_node_initialize, 2);
|
||||
rb_define_method( cNode, "transform", syck_node_transform, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,460 @@
|
|||
//
|
||||
// syck.c
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "syck.h"
|
||||
|
||||
#define SYCK_YAML_MAJOR 1
|
||||
#define SYCK_YAML_MINOR 0
|
||||
#define SYCK_BUFFERSIZE 262144
|
||||
|
||||
//
|
||||
// Custom assert
|
||||
//
|
||||
void
|
||||
syck_assert( char *file_name, unsigned line_num )
|
||||
{
|
||||
fflush( NULL );
|
||||
fprintf( stderr, "\nAssertion failed: %s, line %u\n",
|
||||
file_name, line_num );
|
||||
fflush( stderr );
|
||||
abort();
|
||||
}
|
||||
|
||||
char *
|
||||
syck_strndup( char *buf, long len )
|
||||
{
|
||||
char *new = S_ALLOC_N( char, len + 1 );
|
||||
S_MEMZERO( new, char, len + 1 );
|
||||
S_MEMCPY( new, buf, char, len );
|
||||
}
|
||||
|
||||
//
|
||||
// Default IO functions
|
||||
//
|
||||
long
|
||||
syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
|
||||
{
|
||||
char *beg;
|
||||
long len = 0;
|
||||
|
||||
ASSERT( file != NULL );
|
||||
|
||||
max_size -= skip;
|
||||
len = fread( buf + skip, max_size, sizeof( char ), file->ptr );
|
||||
#if REDEBUG
|
||||
printf( "LEN: %d\n", len );
|
||||
#endif
|
||||
len += skip;
|
||||
buf[len] = '\0';
|
||||
#if REDEBUG
|
||||
printf( "POS: %d\n", len );
|
||||
printf( "BUFFER: %s\n", buf );
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
long
|
||||
syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
|
||||
{
|
||||
char *beg;
|
||||
long len = 0;
|
||||
|
||||
ASSERT( str != NULL );
|
||||
beg = str->ptr;
|
||||
if ( max_size >= 0 )
|
||||
{
|
||||
max_size -= skip;
|
||||
if ( max_size < 0 ) max_size = 0;
|
||||
|
||||
str->ptr += max_size;
|
||||
if ( str->ptr > str->end )
|
||||
{
|
||||
str->ptr = str->end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use exact string length
|
||||
while ( str->ptr < str->end ) {
|
||||
if (*(str->ptr++) == '\n') break;
|
||||
}
|
||||
}
|
||||
if ( beg < str->ptr )
|
||||
{
|
||||
len = str->ptr - beg;
|
||||
S_MEMCPY( buf + skip, beg, char, len );
|
||||
}
|
||||
#if REDEBUG
|
||||
printf( "LEN: %d\n", len );
|
||||
#endif
|
||||
len += skip;
|
||||
buf[len] = '\0';
|
||||
#if REDEBUG
|
||||
printf( "POS: %d\n", len );
|
||||
printf( "BUFFER: %s\n", buf );
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_reset_levels( SyckParser *p )
|
||||
{
|
||||
p->lvl_idx = 1;
|
||||
p->levels[0].spaces = -1;
|
||||
p->levels[0].domain = "yaml.org,2002/";
|
||||
p->levels[0].status = syck_lvl_header;
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_reset_cursor( SyckParser *p )
|
||||
{
|
||||
if ( p->buffer == NULL )
|
||||
{
|
||||
p->buffer = S_ALLOC_N( char, p->bufsize );
|
||||
}
|
||||
p->buffer[0] = '\0';
|
||||
|
||||
p->cursor = NULL;
|
||||
p->lineptr = NULL;
|
||||
p->token = NULL;
|
||||
p->toktmp = NULL;
|
||||
p->marker = NULL;
|
||||
p->limit = NULL;
|
||||
|
||||
p->linect = 0;
|
||||
p->eof = 0;
|
||||
p->last_token = 0;
|
||||
p->force_token = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate the parser
|
||||
//
|
||||
SyckParser *
|
||||
syck_new_parser()
|
||||
{
|
||||
SyckParser *p;
|
||||
p = S_ALLOC( SyckParser );
|
||||
p->lvl_capa = ALLOC_CT;
|
||||
p->levels = S_ALLOC_N( SyckLevel, p->lvl_capa );
|
||||
p->io_type = syck_io_str;
|
||||
p->io.str = NULL;
|
||||
p->syms = NULL;
|
||||
p->anchors = st_init_strtable();
|
||||
p->implicit_typing = 1;
|
||||
p->taguri_expansion = 0;
|
||||
p->bufsize = SYCK_BUFFERSIZE;
|
||||
p->buffer = NULL;
|
||||
syck_parser_reset_levels( p );
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
syck_add_sym( SyckParser *p, char *data )
|
||||
{
|
||||
SYMID id = 0;
|
||||
if ( p->syms == NULL )
|
||||
{
|
||||
p->syms = st_init_numtable();
|
||||
}
|
||||
id = p->syms->num_entries;
|
||||
st_insert( p->syms, id, (st_data_t)data );
|
||||
return id;
|
||||
}
|
||||
|
||||
int
|
||||
syck_lookup_sym( SyckParser *p, SYMID id, char **data )
|
||||
{
|
||||
if ( p->syms == NULL ) return 0;
|
||||
return st_lookup( p->syms, id, (st_data_t *)data );
|
||||
}
|
||||
|
||||
int
|
||||
syck_st_free_nodes( char *key, SyckNode *n, char *arg )
|
||||
{
|
||||
syck_free_node( n );
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
syck_free_parser( SyckParser *p )
|
||||
{
|
||||
char *key;
|
||||
SyckNode *node;
|
||||
|
||||
//
|
||||
// Free the adhoc symbol table
|
||||
//
|
||||
if ( p->syms != NULL )
|
||||
{
|
||||
st_free_table( p->syms );
|
||||
}
|
||||
|
||||
//
|
||||
// Free the anchor table
|
||||
//
|
||||
st_foreach( p->anchors, syck_st_free_nodes, (st_data_t)NULL );
|
||||
st_free_table( p->anchors );
|
||||
|
||||
//
|
||||
// Free all else
|
||||
//
|
||||
S_FREE( p->levels );
|
||||
if ( p->buffer != NULL )
|
||||
{
|
||||
S_FREE( p->buffer );
|
||||
}
|
||||
free_any_io( p );
|
||||
S_FREE( p );
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_handler( SyckParser *p, SyckNodeHandler hdlr )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
p->handler = hdlr;
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_implicit_typing( SyckParser *p, int flag )
|
||||
{
|
||||
p->implicit_typing = ( flag == 0 ? 0 : 1 );
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_taguri_expansion( SyckParser *p, int flag )
|
||||
{
|
||||
p->taguri_expansion = ( flag == 0 ? 0 : 1 );
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_error_handler( SyckParser *p, SyckErrorHandler hdlr )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
p->error_handler = hdlr;
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_file( SyckParser *p, FILE *fp, SyckIoFileRead read )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
free_any_io( p );
|
||||
syck_parser_reset_cursor( p );
|
||||
p->io_type = syck_io_file;
|
||||
p->io.file = S_ALLOC( SyckIoFile );
|
||||
p->io.file->ptr = fp;
|
||||
if ( read != NULL )
|
||||
{
|
||||
p->io.file->read = read;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->io.file->read = syck_io_file_read;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_str( SyckParser *p, char *ptr, long len, SyckIoStrRead read )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
free_any_io( p );
|
||||
syck_parser_reset_cursor( p );
|
||||
p->io_type = syck_io_str;
|
||||
p->io.str = S_ALLOC( SyckIoStr );
|
||||
p->io.str->beg = ptr;
|
||||
p->io.str->ptr = ptr;
|
||||
p->io.str->end = ptr + len;
|
||||
if ( read != NULL )
|
||||
{
|
||||
p->io.str->read = read;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->io.str->read = syck_io_str_read;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_str_auto( SyckParser *p, char *ptr, SyckIoStrRead read )
|
||||
{
|
||||
syck_parser_str( p, ptr, strlen( ptr ), read );
|
||||
}
|
||||
|
||||
SyckLevel *
|
||||
syck_parser_current_level( SyckParser *p )
|
||||
{
|
||||
return &p->levels[p->lvl_idx-1];
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_pop_level( SyckParser *p )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
|
||||
// The root level should never be popped
|
||||
if ( p->lvl_idx <= 1 ) return;
|
||||
|
||||
p->lvl_idx -= 1;
|
||||
if ( p->levels[p->lvl_idx - 1].domain != p->levels[p->lvl_idx].domain )
|
||||
{
|
||||
free( p->levels[p->lvl_idx].domain );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
syck_parser_add_level( SyckParser *p, int len, enum syck_level_status status )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
if ( p->lvl_idx + 1 > p->lvl_capa )
|
||||
{
|
||||
p->lvl_capa += ALLOC_CT;
|
||||
S_REALLOC_N( p->levels, SyckLevel, p->lvl_capa );
|
||||
}
|
||||
|
||||
ASSERT( len > p->levels[p->lvl_idx-1].spaces );
|
||||
p->levels[p->lvl_idx].spaces = len;
|
||||
p->levels[p->lvl_idx].domain = p->levels[p->lvl_idx-1].domain;
|
||||
p->levels[p->lvl_idx].status = status;
|
||||
p->lvl_idx += 1;
|
||||
}
|
||||
|
||||
void
|
||||
free_any_io( SyckParser *p )
|
||||
{
|
||||
ASSERT( p != NULL );
|
||||
switch ( p->io_type )
|
||||
{
|
||||
case syck_io_str:
|
||||
if ( p->io.str != NULL )
|
||||
{
|
||||
S_FREE( p->io.str );
|
||||
p->io.str = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case syck_io_file:
|
||||
if ( p->io.file != NULL )
|
||||
{
|
||||
S_FREE( p->io.file );
|
||||
p->io.file = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
syck_move_tokens( SyckParser *p )
|
||||
{
|
||||
long count, skip;
|
||||
ASSERT( p->buffer != NULL );
|
||||
|
||||
if ( p->token == NULL )
|
||||
return 0;
|
||||
|
||||
skip = p->limit - p->token;
|
||||
if ( skip < 1 )
|
||||
return 0;
|
||||
|
||||
#if REDEBUG
|
||||
printf( "DIFF: %d\n", skip );
|
||||
#endif
|
||||
|
||||
if ( ( count = p->token - p->buffer ) )
|
||||
{
|
||||
S_MEMMOVE( p->buffer, p->token, char, skip );
|
||||
p->token = p->buffer;
|
||||
p->marker -= count;
|
||||
p->cursor -= count;
|
||||
p->toktmp -= count;
|
||||
p->limit -= count;
|
||||
p->lineptr -= count;
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
void
|
||||
syck_check_limit( SyckParser *p, long len )
|
||||
{
|
||||
if ( p->cursor == NULL )
|
||||
{
|
||||
p->cursor = p->buffer;
|
||||
p->lineptr = p->buffer;
|
||||
p->marker = p->buffer;
|
||||
}
|
||||
p->limit = p->buffer + len;
|
||||
}
|
||||
|
||||
long
|
||||
syck_parser_read( SyckParser *p )
|
||||
{
|
||||
long len = 0;
|
||||
long skip = 0;
|
||||
ASSERT( p != NULL );
|
||||
switch ( p->io_type )
|
||||
{
|
||||
case syck_io_str:
|
||||
skip = syck_move_tokens( p );
|
||||
len = (p->io.str->read)( p->buffer, p->io.str, SYCK_BUFFERSIZE - 1, skip );
|
||||
break;
|
||||
|
||||
case syck_io_file:
|
||||
skip = syck_move_tokens( p );
|
||||
len = (p->io.file->read)( p->buffer, p->io.file, SYCK_BUFFERSIZE - 1, skip );
|
||||
break;
|
||||
}
|
||||
syck_check_limit( p, len );
|
||||
return len;
|
||||
}
|
||||
|
||||
long
|
||||
syck_parser_readlen( SyckParser *p, long max_size )
|
||||
{
|
||||
long len = 0;
|
||||
long skip = 0;
|
||||
ASSERT( p != NULL );
|
||||
switch ( p->io_type )
|
||||
{
|
||||
case syck_io_str:
|
||||
skip = syck_move_tokens( p );
|
||||
len = (p->io.str->read)( p->buffer, p->io.str, max_size, skip );
|
||||
break;
|
||||
|
||||
case syck_io_file:
|
||||
skip = syck_move_tokens( p );
|
||||
len = (p->io.file->read)( p->buffer, p->io.file, max_size, skip );
|
||||
break;
|
||||
}
|
||||
syck_check_limit( p, len );
|
||||
return len;
|
||||
}
|
||||
|
||||
SYMID
|
||||
syck_parse( SyckParser *p )
|
||||
{
|
||||
char *line;
|
||||
|
||||
ASSERT( p != NULL );
|
||||
|
||||
p->root = NULL;
|
||||
syck_parser_reset_levels( p );
|
||||
yyparse( p );
|
||||
return p->root;
|
||||
}
|
||||
|
||||
void
|
||||
syck_default_error_handler( SyckParser *p, char *msg )
|
||||
{
|
||||
printf( "Error at [Line %d, Col %d]: %s\n",
|
||||
p->linect,
|
||||
p->cursor - p->lineptr,
|
||||
msg );
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
//
|
||||
// syck.h
|
||||
//
|
||||
// $Author$
|
||||
// $Date$
|
||||
//
|
||||
// Copyright (C) 2003 why the lucky stiff
|
||||
//
|
||||
|
||||
#ifndef SYCK_H
|
||||
#define SYCK_H
|
||||
|
||||
#define SYCK_VERSION "0.25"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ST_H
|
||||
#include <st.h>
|
||||
#else
|
||||
#include "syck_st.h"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// Memory Allocation
|
||||
//
|
||||
#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
void syck_assert( char *, unsigned );
|
||||
# define ASSERT(f) \
|
||||
if ( f ) \
|
||||
{} \
|
||||
else \
|
||||
syck_assert( __FILE__, __LINE__ )
|
||||
#else
|
||||
# define ASSERT(f)
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL (void *)0
|
||||
#endif
|
||||
|
||||
#define ALLOC_CT 8
|
||||
#define S_ALLOC_N(type,n) (type*)malloc(sizeof(type)*(n))
|
||||
#define S_ALLOC(type) (type*)malloc(sizeof(type))
|
||||
#define S_REALLOC_N(var,type,n) (var)=(type*)realloc((char*)(var),sizeof(type)*(n))
|
||||
#define S_FREE(n) free(n); n = NULL;
|
||||
|
||||
#define S_ALLOCA_N(type,n) (type*)alloca(sizeof(type)*(n))
|
||||
|
||||
#define S_MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
|
||||
#define S_MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
|
||||
#define S_MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
|
||||
#define S_MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n))
|
||||
|
||||
#define BLOCK_FOLD 10
|
||||
#define BLOCK_LIT 20
|
||||
#define BLOCK_PLAIN 30
|
||||
#define NL_CHOMP 130
|
||||
#define NL_KEEP 140
|
||||
|
||||
//
|
||||
// Node definitions
|
||||
//
|
||||
#define SYMID unsigned long
|
||||
|
||||
typedef struct _syck_parser SyckParser;
|
||||
typedef struct _syck_file SyckIoFile;
|
||||
typedef struct _syck_str SyckIoStr;
|
||||
typedef struct _syck_node SyckNode;
|
||||
typedef struct _syck_level SyckLevel;
|
||||
|
||||
enum syck_kind_tag {
|
||||
syck_map_kind,
|
||||
syck_seq_kind,
|
||||
syck_str_kind
|
||||
};
|
||||
|
||||
enum map_part {
|
||||
map_key,
|
||||
map_value
|
||||
};
|
||||
|
||||
struct _syck_node {
|
||||
// Symbol table ID
|
||||
SYMID id;
|
||||
// Underlying kind
|
||||
enum syck_kind_tag kind;
|
||||
// Fully qualified tag-uri for type
|
||||
char *type_id;
|
||||
// Anchor name
|
||||
char *anchor;
|
||||
union {
|
||||
// Storage for map data
|
||||
struct SyckMap {
|
||||
SYMID *keys;
|
||||
SYMID *values;
|
||||
long capa;
|
||||
long idx;
|
||||
} *pairs;
|
||||
// Storage for sequence data
|
||||
struct SyckSeq {
|
||||
SYMID *items;
|
||||
long capa;
|
||||
long idx;
|
||||
} *list;
|
||||
// Storage for string data
|
||||
struct SyckStr {
|
||||
char *ptr;
|
||||
long len;
|
||||
} *str;
|
||||
} data;
|
||||
};
|
||||
|
||||
//
|
||||
// Parser definitions
|
||||
//
|
||||
typedef SYMID (*SyckNodeHandler)(SyckParser *, SyckNode *);
|
||||
typedef void (*SyckErrorHandler)(SyckParser *, char *);
|
||||
typedef long (*SyckIoFileRead)(char *, SyckIoFile *, long, long);
|
||||
typedef long (*SyckIoStrRead)(char *, SyckIoStr *, long, long);
|
||||
|
||||
enum syck_io_type {
|
||||
syck_io_str,
|
||||
syck_io_file
|
||||
};
|
||||
|
||||
enum syck_level_status {
|
||||
syck_lvl_header,
|
||||
syck_lvl_doc,
|
||||
syck_lvl_seq,
|
||||
syck_lvl_block,
|
||||
syck_lvl_str,
|
||||
syck_lvl_inline,
|
||||
syck_lvl_end,
|
||||
syck_lvl_pause
|
||||
};
|
||||
|
||||
struct _syck_parser {
|
||||
// Root node
|
||||
SYMID root;
|
||||
// Implicit typing flag
|
||||
int implicit_typing, taguri_expansion;
|
||||
// Scripting language function to handle nodes
|
||||
SyckNodeHandler handler;
|
||||
// Error handler
|
||||
SyckErrorHandler error_handler;
|
||||
// IO type
|
||||
enum syck_io_type io_type;
|
||||
// Custom buffer size
|
||||
size_t bufsize;
|
||||
// Buffer pointers
|
||||
char *buffer, *lineptr, *toktmp, *token, *cursor, *marker, *limit;
|
||||
// Line counter
|
||||
int linect;
|
||||
// Last token from yylex()
|
||||
int last_token;
|
||||
// Force a token upon next call to yylex()
|
||||
int force_token;
|
||||
// EOF flag
|
||||
int eof;
|
||||
union {
|
||||
struct _syck_file {
|
||||
FILE *ptr;
|
||||
SyckIoFileRead read;
|
||||
} *file;
|
||||
struct _syck_str {
|
||||
char *beg, *ptr, *end;
|
||||
SyckIoStrRead read;
|
||||
} *str;
|
||||
} io;
|
||||
// Symbol table
|
||||
st_table *anchors;
|
||||
// Optional symbol table for SYMIDs
|
||||
st_table *syms;
|
||||
// Levels of indentation
|
||||
struct _syck_level {
|
||||
int spaces;
|
||||
char *domain;
|
||||
enum syck_level_status status;
|
||||
} *levels;
|
||||
int lvl_idx;
|
||||
int lvl_capa;
|
||||
void *bonus;
|
||||
};
|
||||
|
||||
//
|
||||
// Handler prototypes
|
||||
//
|
||||
SYMID syck_hdlr_add_node( SyckParser *, SyckNode * );
|
||||
SyckNode *syck_hdlr_add_anchor( SyckParser *, char *, SyckNode * );
|
||||
SyckNode *syck_hdlr_add_alias( SyckParser *, char * );
|
||||
void syck_add_transfer( char *, SyckNode *, int );
|
||||
void syck_xprivate( SyckNode *, char *, int );
|
||||
void syck_taguri( SyckNode *, char *, char *, int );
|
||||
int syck_add_sym( SyckParser *, char * );
|
||||
int syck_lookup_sym( SyckParser *, SYMID, char ** );
|
||||
int syck_try_implicit( SyckNode * );
|
||||
void syck_fold_format( struct SyckStr *, int, int, int );
|
||||
void try_tag_implicit( SyckNode *, int );
|
||||
|
||||
//
|
||||
// API prototypes
|
||||
//
|
||||
char *syck_strndup( char *, long );
|
||||
long syck_io_file_read( char *, SyckIoFile *, long, long );
|
||||
long syck_io_str_read( char *, SyckIoStr *, long, long );
|
||||
SyckParser *syck_new_parser();
|
||||
void syck_free_parser( SyckParser * );
|
||||
void syck_parser_implicit_typing( SyckParser *, int );
|
||||
void syck_parser_taguri_expansion( SyckParser *, int );
|
||||
void syck_parser_handler( SyckParser *, SyckNodeHandler );
|
||||
void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
|
||||
void syck_parser_file( SyckParser *, FILE *, SyckIoFileRead );
|
||||
void syck_parser_str( SyckParser *, char *, long, SyckIoStrRead );
|
||||
void syck_parser_str_auto( SyckParser *, char *, SyckIoStrRead );
|
||||
SyckLevel *syck_parser_current_level( SyckParser * );
|
||||
void syck_parser_add_level( SyckParser *, int, enum syck_level_status );
|
||||
void free_any_io( SyckParser * );
|
||||
long syck_parser_read( SyckParser * );
|
||||
long syck_parser_readlen( SyckParser *, long );
|
||||
void syck_parser_init( SyckParser *, int );
|
||||
SYMID syck_parse( SyckParser * );
|
||||
void syck_default_error_handler( SyckParser *, char * );
|
||||
|
||||
//
|
||||
// Allocation prototypes
|
||||
//
|
||||
SyckNode *syck_alloc_map();
|
||||
SyckNode *syck_alloc_seq();
|
||||
SyckNode *syck_alloc_str();
|
||||
void syck_free_node( SyckNode * );
|
||||
void syck_free_members( SyckNode * );
|
||||
SyckNode *syck_new_str( char * );
|
||||
SyckNode *syck_new_str2( char *, long );
|
||||
void syck_str_blow_away_commas( SyckNode * );
|
||||
char *syck_str_read( SyckNode * );
|
||||
SyckNode *syck_new_map( SYMID, SYMID );
|
||||
void syck_map_add( SyckNode *, SYMID, SYMID );
|
||||
SYMID syck_map_read( SyckNode *, enum map_part, long );
|
||||
long syck_map_count( SyckNode * );
|
||||
void syck_map_update( SyckNode *, SyckNode * );
|
||||
SyckNode *syck_new_seq( SYMID );
|
||||
void syck_seq_add( SyckNode *, SYMID );
|
||||
SYMID syck_seq_read( SyckNode *, long );
|
||||
long syck_seq_count( SyckNode * );
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* ifndef SYCK_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,119 @@
|
|||
# vim:sw=4:ts=4
|
||||
# $Id$
|
||||
#
|
||||
# YAML.rb
|
||||
#
|
||||
# Loads the parser/loader and emitter/writer.
|
||||
#
|
||||
|
||||
module YAML
|
||||
|
||||
begin
|
||||
require 'syck'
|
||||
Parser = YAML::Syck::Parser
|
||||
rescue LoadError
|
||||
require 'yaml/parser'
|
||||
Parser = YAML::Parser
|
||||
end
|
||||
require 'yaml/emitter'
|
||||
require 'yaml/rubytypes'
|
||||
|
||||
#
|
||||
# Allocate blank object
|
||||
#
|
||||
def YAML.object_maker( obj_class, val )
|
||||
if Hash === val
|
||||
name = obj_class.name
|
||||
o = ::Marshal.load( sprintf( "\004\006o:%c%s\000", name.length + 5, name ))
|
||||
val.each_pair { |k,v|
|
||||
o.instance_eval "@#{k} = v"
|
||||
}
|
||||
o
|
||||
else
|
||||
raise YAML::Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Input methods
|
||||
#
|
||||
|
||||
#
|
||||
# Load a single document from the current stream
|
||||
#
|
||||
def YAML.load( io )
|
||||
yp = YAML::Parser.new.parse( io )
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a single document from the current stream
|
||||
#
|
||||
def YAML.parse( io )
|
||||
yp = YAML::Parser.new( :Model => :Generic ).parse( io )
|
||||
end
|
||||
|
||||
#
|
||||
# Load all documents from the current stream
|
||||
#
|
||||
def YAML.each_document( io, &doc_proc )
|
||||
yp = YAML::Parser.new.parse_documents( io, &doc_proc )
|
||||
end
|
||||
|
||||
#
|
||||
# Identical to each_document
|
||||
#
|
||||
def YAML.load_documents( io, &doc_proc )
|
||||
YAML.each_document( io, &doc_proc )
|
||||
end
|
||||
|
||||
#
|
||||
# Parse all documents from the current stream
|
||||
#
|
||||
def YAML.each_node( io, &doc_proc )
|
||||
yp = YAML::Parser.new( :Model => :Generic ).parse_documents( io, &doc_proc )
|
||||
end
|
||||
|
||||
#
|
||||
# Parse all documents from the current stream
|
||||
#
|
||||
def YAML.parse_documents( io, &doc_proc )
|
||||
YAML.each_node( io, &doc_proc )
|
||||
end
|
||||
|
||||
#
|
||||
# Load all documents from the current stream
|
||||
#
|
||||
def YAML.load_stream( io )
|
||||
yp = YAML::Parser.new
|
||||
d = nil
|
||||
yp.parse_documents( io ) { |doc|
|
||||
d = YAML::Stream.new( yp.options ) if not d
|
||||
d.add( doc )
|
||||
}
|
||||
return d
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# ryan: You know how Kernel.p is a really convenient way to dump ruby
|
||||
# structures? The only downside is that it's not as legible as
|
||||
# YAML.
|
||||
#
|
||||
# _why: (listening)
|
||||
#
|
||||
# ryan: I know you don't want to urinate all over your users' namespaces.
|
||||
# But, on the other hand, convenience of dumping for debugging is,
|
||||
# IMO, a big YAML use case.
|
||||
#
|
||||
# _why: Go nuts! Have a pony parade!
|
||||
#
|
||||
# ryan: Either way, I certainly will have a pony parade.
|
||||
#
|
||||
module Kernel
|
||||
def y( x )
|
||||
puts x.to_yaml
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
#
|
||||
# YAML::BaseNode class
|
||||
#
|
||||
require 'yaml/ypath'
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# YAML Generic Model container
|
||||
#
|
||||
module BaseNode
|
||||
|
||||
#
|
||||
# Search for YPath entry and return
|
||||
# qualified nodes.
|
||||
#
|
||||
def select( ypath_str )
|
||||
matches = match_path( ypath_str )
|
||||
|
||||
#
|
||||
# Create a new generic view of the elements selected
|
||||
#
|
||||
if matches
|
||||
result = []
|
||||
matches.each { |m|
|
||||
result.push m.last
|
||||
}
|
||||
YamlNode.new( 'seq', result )
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Search for YPath entry and return
|
||||
# transformed nodes.
|
||||
#
|
||||
def select!( ypath_str )
|
||||
matches = match_path( ypath_str )
|
||||
|
||||
#
|
||||
# Create a new generic view of the elements selected
|
||||
#
|
||||
if matches
|
||||
result = []
|
||||
matches.each { |m|
|
||||
result.push m.last.transform
|
||||
}
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Search for YPath entry and return a list of
|
||||
# qualified paths.
|
||||
#
|
||||
def search( ypath_str )
|
||||
matches = match_path( ypath_str )
|
||||
|
||||
if matches
|
||||
matches.collect { |m|
|
||||
path = []
|
||||
m.each_index { |i|
|
||||
path.push m[i] if ( i % 2 ).zero?
|
||||
}
|
||||
"/" + path.compact.join( "/" )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def at( seg )
|
||||
if Hash === @value and @value.has_key?( seg )
|
||||
@value[seg][1]
|
||||
elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i]
|
||||
@value[seg.to_i]
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# YPath search returning a complete depth array
|
||||
#
|
||||
def match_path( ypath_str )
|
||||
depth = 0
|
||||
matches = []
|
||||
YPath.each_path( ypath_str ) do |ypath|
|
||||
seg = match_segment( ypath, 0 )
|
||||
matches += seg if seg
|
||||
end
|
||||
matches.uniq
|
||||
end
|
||||
|
||||
#
|
||||
# Search a node for a single YPath segment
|
||||
#
|
||||
def match_segment( ypath, depth )
|
||||
deep_nodes = []
|
||||
seg = ypath.segments[ depth ]
|
||||
if seg == "/"
|
||||
unless String === @value
|
||||
idx = -1
|
||||
@value.collect { |v|
|
||||
idx += 1
|
||||
if Hash === @value
|
||||
match_init = [v[0], v[1][1]]
|
||||
match_deep = v[1][1].match_segment( ypath, depth )
|
||||
else
|
||||
match_init = [idx, v]
|
||||
match_deep = v.match_segment( ypath, depth )
|
||||
end
|
||||
if match_deep
|
||||
match_deep.each { |m|
|
||||
deep_nodes.push( match_init + m )
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
depth += 1
|
||||
seg = ypath.segments[ depth ]
|
||||
end
|
||||
match_nodes =
|
||||
case seg
|
||||
when "."
|
||||
[[nil, self]]
|
||||
when ".."
|
||||
[["..", nil]]
|
||||
when "*"
|
||||
if @value.is_a? Enumerable
|
||||
idx = -1
|
||||
@value.collect { |h|
|
||||
idx += 1
|
||||
if Hash === @value
|
||||
[h[0], h[1][1]]
|
||||
else
|
||||
[idx, h]
|
||||
end
|
||||
}
|
||||
end
|
||||
else
|
||||
if seg =~ /^"(.*)"$/
|
||||
seg = $1
|
||||
elsif seg =~ /^'(.*)'$/
|
||||
seg = $1
|
||||
end
|
||||
if ( v = at( seg ) )
|
||||
[[ seg, v ]]
|
||||
end
|
||||
end
|
||||
return deep_nodes unless match_nodes
|
||||
pred = ypath.predicates[ depth ]
|
||||
if pred
|
||||
case pred
|
||||
when /^\.=/
|
||||
pred = $'
|
||||
match_nodes.reject! { |n|
|
||||
n.last.value != pred
|
||||
}
|
||||
else
|
||||
match_nodes.reject! { |n|
|
||||
n.last.at( pred ).nil?
|
||||
}
|
||||
end
|
||||
end
|
||||
return match_nodes + deep_nodes unless ypath.segments.length > depth + 1
|
||||
|
||||
#puts "DEPTH: #{depth + 1}"
|
||||
deep_nodes = []
|
||||
match_nodes.each { |n|
|
||||
if n[1].is_a? YamlNode
|
||||
match_deep = n[1].match_segment( ypath, depth + 1 )
|
||||
if match_deep
|
||||
match_deep.each { |m|
|
||||
deep_nodes.push( n + m )
|
||||
}
|
||||
end
|
||||
else
|
||||
deep_nodes = []
|
||||
end
|
||||
}
|
||||
deep_nodes = nil if deep_nodes.length == 0
|
||||
deep_nodes
|
||||
end
|
||||
|
||||
#
|
||||
# We want the node to act like as Hash
|
||||
# if it is.
|
||||
#
|
||||
def []( *k )
|
||||
if Hash === @value
|
||||
v = @value.[]( *k )
|
||||
v[1] if v
|
||||
elsif Array === @value
|
||||
@value.[]( *k )
|
||||
end
|
||||
end
|
||||
|
||||
def children
|
||||
if Hash === @value
|
||||
@value.values.collect { |c| c[1] }
|
||||
elsif Array === @value
|
||||
@value
|
||||
end
|
||||
end
|
||||
|
||||
def children_with_index
|
||||
if Hash === @value
|
||||
@value.keys.collect { |i| [self[i], i] }
|
||||
elsif Array === @value
|
||||
i = -1; @value.collect { |v| i += 1; [v, i] }
|
||||
end
|
||||
end
|
||||
|
||||
def emit
|
||||
transform.to_yaml
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# Constants used throughout the library
|
||||
#
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
VERSION = '0.60'
|
||||
SUPPORTED_YAML_VERSIONS = ['1.0']
|
||||
|
||||
#
|
||||
# Parser tokens
|
||||
#
|
||||
WORD_CHAR = 'A-Za-z0-9'
|
||||
PRINTABLE_CHAR = '-_A-Za-z0-9!?/()$\'". '
|
||||
NOT_PLAIN_CHAR = '\x7f\x0-\x1f\x80-\x9f'
|
||||
ESCAPE_CHAR = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f]'
|
||||
INDICATOR_CHAR = '*&!|\\\\^@%{}[]='
|
||||
SPACE_INDICATORS = '-#:,?'
|
||||
RESTRICTED_INDICATORS = '#:,}]'
|
||||
DNS_COMP_RE = "\\w(?:[-\\w]*\\w)?"
|
||||
DNS_NAME_RE = "(?:(?:#{DNS_COMP_RE}\\.)+#{DNS_COMP_RE}|#{DNS_COMP_RE})"
|
||||
ESCAPES = %w{\z \x01 \x02 \x03 \x04 \x05 \x06 \a
|
||||
\x08 \t \n \v \f \r \x0e \x0f
|
||||
\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17
|
||||
\x18 \x19 \x1a \e \x1c \x1d \x1e \x1f
|
||||
}
|
||||
UNESCAPES = {
|
||||
'z' => "\x00", 'a' => "\x07", 'b' => "\x08", 't' => "\x09",
|
||||
'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c",
|
||||
'r' => "\x0d", 'e' => "\x1b", '\\' => '\\',
|
||||
}
|
||||
|
||||
#
|
||||
# Default settings
|
||||
#
|
||||
DEFAULTS = {
|
||||
:Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.0',
|
||||
:SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false,
|
||||
:WidthType => 'absolute', :BestWidth => 80,
|
||||
:UseBlock => false, :UseFold => false, :Encoding => :None
|
||||
}
|
||||
TRANSFER_DOMAINS = {
|
||||
'yaml.org,2002' => {},
|
||||
'ruby.yaml.org,2002' => {}
|
||||
}
|
||||
PRIVATE_TYPES = {}
|
||||
IMPLICIT_TYPES = [ 'null', 'bool', 'time', 'int', 'float' ]
|
||||
|
||||
end
|
|
@ -0,0 +1,111 @@
|
|||
require 'yaml'
|
||||
require 'dbm'
|
||||
#
|
||||
# YAML + DBM = YDBM
|
||||
# - Same interface as DBM class
|
||||
#
|
||||
module YAML
|
||||
|
||||
class DBM < ::DBM
|
||||
VERSION = "0.1"
|
||||
def []( key )
|
||||
fetch( key )
|
||||
end
|
||||
def []=( key, val )
|
||||
store( key, val )
|
||||
end
|
||||
def fetch( keystr, ifnone = nil )
|
||||
begin
|
||||
val = super( keystr )
|
||||
return YAML::load( val ) if String === val
|
||||
rescue IndexError
|
||||
end
|
||||
if block_given?
|
||||
yield keystr
|
||||
else
|
||||
ifnone
|
||||
end
|
||||
end
|
||||
def index( keystr )
|
||||
super( keystr.to_yaml )
|
||||
end
|
||||
def indexes( *keys )
|
||||
keys.collect { |k| fetch( k ) }
|
||||
end
|
||||
def delete( key )
|
||||
v = super( key )
|
||||
if String === v
|
||||
v = YAML::load( v )
|
||||
end
|
||||
v
|
||||
end
|
||||
def delete_if
|
||||
del_keys = keys.dup
|
||||
del_keys.delete_if { |k| yield( k, fetch( k ) ) == false }
|
||||
del_keys.each { |k| delete( k ) }
|
||||
self
|
||||
end
|
||||
def reject
|
||||
hsh = self.to_hash
|
||||
hsh.reject { |k,v| yield k, v }
|
||||
end
|
||||
def each_pair
|
||||
keys.each { |k| yield k, fetch( k ) }
|
||||
self
|
||||
end
|
||||
def each_value
|
||||
super { |v| yield YAML::load( v ) }
|
||||
self
|
||||
end
|
||||
def values
|
||||
super.collect { |v| YAML::load( v ) }
|
||||
end
|
||||
def has_value?( val )
|
||||
each_value { |v| return true if v == val }
|
||||
return false
|
||||
end
|
||||
def invert
|
||||
h = {}
|
||||
keys.each { |k| h[ self.fetch( k ) ] = k }
|
||||
h
|
||||
end
|
||||
def replace( hsh )
|
||||
clear
|
||||
update( hsh )
|
||||
end
|
||||
def shift
|
||||
a = super
|
||||
a[1] = YAML::load( a[1] ) if a
|
||||
a
|
||||
end
|
||||
def select( *keys )
|
||||
if block_given?
|
||||
self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact
|
||||
else
|
||||
indexes( *keys )
|
||||
end
|
||||
end
|
||||
def store( key, val )
|
||||
super( key, val.to_yaml )
|
||||
val
|
||||
end
|
||||
def update( hsh )
|
||||
hsh.keys.each do |k|
|
||||
self.store( k, hsh.fetch( k ) )
|
||||
end
|
||||
self
|
||||
end
|
||||
def to_a
|
||||
a = []
|
||||
keys.each { |k| a.push [ k, self.fetch( k ) ] }
|
||||
a
|
||||
end
|
||||
def to_hash
|
||||
h = {}
|
||||
keys.each { |k| h[ k ] = self.fetch( k ) }
|
||||
h
|
||||
end
|
||||
alias :each :each_pair
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,330 @@
|
|||
#
|
||||
# Output classes and methods
|
||||
#
|
||||
|
||||
require 'yaml/constants'
|
||||
require 'yaml/encoding'
|
||||
require 'yaml/error'
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Emit a set of values
|
||||
#
|
||||
|
||||
class Emitter
|
||||
attr_accessor :options
|
||||
def initialize( opts )
|
||||
opts = {} if opts.class != Hash
|
||||
@options = YAML::DEFAULTS.dup.update( opts )
|
||||
@headless = 0
|
||||
@seq_map = false
|
||||
@anchors = {}
|
||||
@anchor_extras = {}
|
||||
@active_anchors = []
|
||||
@level = -1
|
||||
self.clear
|
||||
end
|
||||
|
||||
def clear
|
||||
@buffer = []
|
||||
end
|
||||
|
||||
#
|
||||
# Version string
|
||||
#
|
||||
def version_s
|
||||
" %YAML:#{@options[:Version]}" if @options[:UseVersion]
|
||||
end
|
||||
|
||||
#
|
||||
# Header
|
||||
#
|
||||
def header
|
||||
if @headless.nonzero?
|
||||
""
|
||||
else
|
||||
"---#{version_s} "
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Emit binary data
|
||||
#
|
||||
def binary_base64( value )
|
||||
self << "!binary "
|
||||
self.node_text( [value].pack("m"), '|' )
|
||||
end
|
||||
|
||||
#
|
||||
# Emit plain, normal flowing text
|
||||
#
|
||||
def node_text( value, block = '>' )
|
||||
valx = value.dup
|
||||
if @options[:UseBlock]
|
||||
block = '|'
|
||||
elsif not @options[:UseFold] and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/
|
||||
block = '|'
|
||||
end
|
||||
str = block.dup
|
||||
if valx =~ /\n\Z\n/
|
||||
str << "+"
|
||||
elsif valx =~ /\Z\n/
|
||||
else
|
||||
str << "-"
|
||||
end
|
||||
if valx =~ /#{YAML::ESCAPE_CHAR}/
|
||||
valx = YAML::escape( valx )
|
||||
end
|
||||
if valx =~ /\A[ \t#]/
|
||||
str << @options[:Indent].to_s
|
||||
end
|
||||
if block == '>'
|
||||
valx = fold( valx )
|
||||
end
|
||||
self << str + indent_text( valx ) + "\n"
|
||||
end
|
||||
|
||||
#
|
||||
# Emit a simple, unqouted string
|
||||
#
|
||||
def simple( value )
|
||||
self << value.to_s
|
||||
end
|
||||
|
||||
#
|
||||
# Emit double-quoted string
|
||||
#
|
||||
def double( value )
|
||||
"\"#{YAML.escape( value )}\""
|
||||
end
|
||||
|
||||
#
|
||||
# Emit single-quoted string
|
||||
#
|
||||
def single( value )
|
||||
"'#{value}'"
|
||||
end
|
||||
|
||||
#
|
||||
# Write a text block with the current indent
|
||||
#
|
||||
def indent_text( text )
|
||||
return "" if text.to_s.empty?
|
||||
spacing = " " * ( @level * @options[:Indent] )
|
||||
return "\n" + text.gsub( /^([^\n])/, "#{spacing}\\1" )
|
||||
end
|
||||
|
||||
#
|
||||
# Write a current indent
|
||||
#
|
||||
def indent
|
||||
#p [ self.id, @level, :INDENT ]
|
||||
return " " * ( @level * @options[:Indent] )
|
||||
end
|
||||
|
||||
#
|
||||
# Add indent to the buffer
|
||||
#
|
||||
def indent!
|
||||
self << indent
|
||||
end
|
||||
|
||||
#
|
||||
# Folding paragraphs within a column
|
||||
#
|
||||
def fold( value )
|
||||
value.gsub!( /\A\n+/, '' )
|
||||
folded = $&.to_s
|
||||
width = (0..@options[:BestWidth])
|
||||
while not value.empty?
|
||||
last = value.index( /(\n+)/ )
|
||||
chop_s = false
|
||||
if width.include?( last )
|
||||
last += $1.length - 1
|
||||
elsif width.include?( value.length )
|
||||
last = value.length
|
||||
else
|
||||
last = value.rindex( /[ \t]/, @options[:BestWidth] )
|
||||
chop_s = true
|
||||
end
|
||||
folded += value.slice!( 0, width.include?( last ) ? last + 1 : @options[:BestWidth] )
|
||||
folded.chop! if chop_s
|
||||
folded += "\n" unless value.empty?
|
||||
end
|
||||
folded
|
||||
end
|
||||
|
||||
#
|
||||
# Quick mapping
|
||||
#
|
||||
def map( type, &e )
|
||||
val = Mapping.new
|
||||
e.call( val )
|
||||
self << "#{type} " if type.length.nonzero?
|
||||
|
||||
#
|
||||
# Empty hashes
|
||||
#
|
||||
if val.length.zero?
|
||||
self << "{}"
|
||||
else
|
||||
if @buffer.length == 1 and @options[:UseHeader] == false and type.length.zero?
|
||||
@headless = 1
|
||||
end
|
||||
|
||||
defkey = @options.delete( :DefaultKey )
|
||||
if defkey
|
||||
seq_map_shortcut
|
||||
self << "= : "
|
||||
defkey.to_yaml( :Emitter => self )
|
||||
end
|
||||
|
||||
#
|
||||
# Emit the key and value
|
||||
#
|
||||
val.each { |v|
|
||||
seq_map_shortcut
|
||||
if v[0].is_complex_yaml?
|
||||
self << "? "
|
||||
end
|
||||
v[0].to_yaml( :Emitter => self )
|
||||
if v[0].is_complex_yaml?
|
||||
self << "\n"
|
||||
indent!
|
||||
end
|
||||
self << ": "
|
||||
v[1].to_yaml( :Emitter => self )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def seq_map_shortcut
|
||||
if @seq_map
|
||||
@anchor_extras[@buffer.length - 1] = "\n" + indent
|
||||
@seq_map = false
|
||||
else
|
||||
self << "\n"
|
||||
indent!
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Quick sequence
|
||||
#
|
||||
def seq( type, &e )
|
||||
val = Sequence.new
|
||||
e.call( val )
|
||||
self << "#{type} " if type.length.nonzero?
|
||||
|
||||
#
|
||||
# Empty arrays
|
||||
#
|
||||
if val.length.zero?
|
||||
self << "[]"
|
||||
else
|
||||
if @buffer.length == 1 and @options[:UseHeader] == false and type.length.zero?
|
||||
@headless = 1
|
||||
end
|
||||
#
|
||||
# Emit the key and value
|
||||
#
|
||||
val.each { |v|
|
||||
self << "\n"
|
||||
indent!
|
||||
self << "- "
|
||||
@seq_map = true if v.class == Hash
|
||||
v.to_yaml( :Emitter => self )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Concatenate to the buffer
|
||||
#
|
||||
def <<( str )
|
||||
#p [ self.id, @level, str ]
|
||||
@buffer.last << str
|
||||
end
|
||||
|
||||
#
|
||||
# Monitor objects and allow references
|
||||
#
|
||||
def start_object( oid )
|
||||
@level += 1
|
||||
@buffer.push( "" )
|
||||
#p [ self.id, @level, :OPEN ]
|
||||
idx = nil
|
||||
if oid
|
||||
if @anchors.has_key?( oid )
|
||||
idx = @active_anchors.index( oid )
|
||||
unless idx
|
||||
idx = @active_anchors.length
|
||||
af_str = "&#{@options[:AnchorFormat]} " % [ idx + 1 ]
|
||||
af_str += @anchor_extras[ @anchors[ oid ] ].to_s
|
||||
@buffer[ @anchors[ oid ] ][0,0] = af_str
|
||||
@headless = 0 if @anchors[ oid ].zero?
|
||||
end
|
||||
idx += 1
|
||||
@active_anchors.push( oid )
|
||||
else
|
||||
@anchors[ oid ] = @buffer.length - 1
|
||||
end
|
||||
end
|
||||
return idx
|
||||
end
|
||||
|
||||
#
|
||||
# Output method
|
||||
#
|
||||
def end_object
|
||||
@level -= 1
|
||||
@buffer.push( "" )
|
||||
#p [ self.id, @level, :END ]
|
||||
if @level < 0
|
||||
YAML.internal_to_utf( header + @buffer.to_s[@headless..-1], @options[:Encoding] )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Emitter helper classes
|
||||
#
|
||||
class Mapping < Array
|
||||
def add( k, v )
|
||||
push [k, v]
|
||||
end
|
||||
end
|
||||
|
||||
class Sequence < Array
|
||||
def add( v )
|
||||
push v
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Allocate an Emitter if needed
|
||||
#
|
||||
def YAML.quick_emit( oid, opts = {}, &e )
|
||||
old_opt = nil
|
||||
if opts[:Emitter].is_a? YAML::Emitter
|
||||
out = opts.delete( :Emitter )
|
||||
old_opt = out.options.dup
|
||||
out.options.update( opts )
|
||||
else
|
||||
out = YAML::Emitter.new( opts )
|
||||
end
|
||||
aidx = out.start_object( oid )
|
||||
if aidx
|
||||
out.simple( "*#{out.options[:AnchorFormat]} " % [ aidx ] )
|
||||
else
|
||||
e.call( out )
|
||||
end
|
||||
if old_opt.is_a? Hash
|
||||
out.options = old_opt
|
||||
end
|
||||
out.end_object
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
#
|
||||
# Handle Unicode-to-Internal conversion
|
||||
#
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Encodings ( $-K to ICONV )
|
||||
#
|
||||
CHARSETS = {
|
||||
'NONE' => 'LATIN1',
|
||||
'ASCII' => 'US-ASCII',
|
||||
'UTF-8' => 'UTF-8',
|
||||
'EUC' => 'EUC-JP',
|
||||
'SJIS' => 'SHIFT-JIS'
|
||||
}
|
||||
|
||||
#
|
||||
# YAML documents can be in UTF-8, UTF-16 or UTF-32
|
||||
# So let's read and write in Unicode
|
||||
#
|
||||
|
||||
@@unicode = false
|
||||
begin
|
||||
require 'iconv'
|
||||
DEFAULTS[:Encoding] = :Utf8
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
def YAML.unicode; @@unicode; end
|
||||
def YAML.unicode=( bool ); @@unicode = bool; end
|
||||
|
||||
#
|
||||
# Unicode conversion
|
||||
#
|
||||
|
||||
def YAML.utf_to_internal( str, from_enc )
|
||||
return unless str
|
||||
to_enc = CHARSETS[$-K]
|
||||
case from_enc
|
||||
when :Utf32
|
||||
Iconv.iconv( to_enc, 'UTF-32', str )[0]
|
||||
when :Utf16
|
||||
Iconv.iconv( to_enc, 'UTF-16', str )[0]
|
||||
when :Utf8
|
||||
Iconv.iconv( to_enc, 'UTF-8', str )[0]
|
||||
when :None
|
||||
str
|
||||
else
|
||||
raise YAML::Error, ERROR_UNSUPPORTED_ENCODING % from_enc.inspect
|
||||
end
|
||||
end
|
||||
|
||||
def YAML.internal_to_utf( str, to_enc )
|
||||
return unless str
|
||||
from_enc = CHARSETS[$-K]
|
||||
case to_enc
|
||||
when :Utf32
|
||||
Iconv.iconv( 'UTF-32', from_enc, str )[0]
|
||||
when :Utf16
|
||||
Iconv.iconv( 'UTF-16', from_enc, str )[0]
|
||||
when :Utf8
|
||||
Iconv.iconv( 'UTF-8', from_enc, str )[0]
|
||||
when :None
|
||||
str
|
||||
else
|
||||
raise YAML::Error, ERROR_UNSUPPORTED_ENCODING % to_enc.inspect
|
||||
end
|
||||
end
|
||||
|
||||
def YAML.sniff_encoding( str )
|
||||
unless YAML::unicode
|
||||
:None
|
||||
else
|
||||
case str
|
||||
when /^\x00\x00\xFE\xFF/ # UTF-32
|
||||
:Utf32
|
||||
when /^\xFE\xFF/ # UTF-32BE
|
||||
:Utf16
|
||||
else
|
||||
:Utf8
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def YAML.enc_separator( enc )
|
||||
case enc
|
||||
when :Utf32
|
||||
"\000\000\000\n"
|
||||
when :Utf16
|
||||
"\000\n"
|
||||
when :Utf8
|
||||
"\n"
|
||||
when :None
|
||||
"\n"
|
||||
else
|
||||
raise YAML::Error, ERROR_UNSUPPORTED_ENCODING % enc.inspect
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Escape the string, condensing common escapes
|
||||
#
|
||||
def YAML.escape( value )
|
||||
value.gsub( /\\/, "\\\\\\" ).gsub( /"/, "\\\"" ).gsub( /([\x00-\x1f])/ ) { |x| ESCAPES[ x.unpack("C")[0] ] }
|
||||
end
|
||||
|
||||
#
|
||||
# Unescape the condenses escapes
|
||||
#
|
||||
def YAML.unescape( value )
|
||||
value.gsub( /\\(?:([nevbr\\fartz])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) { |x|
|
||||
if $3
|
||||
["#$3".hex ].pack('U*')
|
||||
elsif $2
|
||||
[$2].pack( "H2" )
|
||||
else
|
||||
UNESCAPES[$1]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# Error messages and exception class
|
||||
#
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Error messages
|
||||
#
|
||||
|
||||
ERROR_NO_HEADER_NODE = "With UseHeader=false, the node Array or Hash must have elements"
|
||||
ERROR_NEED_HEADER = "With UseHeader=false, the node must be an Array or Hash"
|
||||
ERROR_BAD_EXPLICIT = "Unsupported explicit transfer: '%s'"
|
||||
ERROR_MANY_EXPLICIT = "More than one explicit transfer"
|
||||
ERROR_MANY_IMPLICIT = "More than one implicit request"
|
||||
ERROR_NO_ANCHOR = "No anchor for alias '%s'"
|
||||
ERROR_BAD_ANCHOR = "Invalid anchor: %s"
|
||||
ERROR_MANY_ANCHOR = "More than one anchor"
|
||||
ERROR_ANCHOR_ALIAS = "Can't define both an anchor and an alias"
|
||||
ERROR_BAD_ALIAS = "Invalid alias: %s"
|
||||
ERROR_MANY_ALIAS = "More than one alias"
|
||||
ERROR_ZERO_INDENT = "Can't use zero as an indentation width"
|
||||
ERROR_UNSUPPORTED_VERSION = "This release of YAML.rb does not support YAML version %s"
|
||||
ERROR_UNSUPPORTED_ENCODING = "Attempt to use unsupported encoding: %s"
|
||||
|
||||
#
|
||||
# YAML Error classes
|
||||
#
|
||||
|
||||
class Error < StandardError; end
|
||||
class ParseError < Error; end
|
||||
|
||||
end
|
|
@ -0,0 +1,558 @@
|
|||
require 'date'
|
||||
#
|
||||
# Type conversions
|
||||
#
|
||||
class Object
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml_type
|
||||
"!ruby/object:#{self.class}"
|
||||
end
|
||||
def to_yaml_properties
|
||||
instance_variables.sort
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out.map( self.to_yaml_type ) { |map|
|
||||
to_yaml_properties.each { |m|
|
||||
map.add( m[1..-1], instance_eval( m ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_ruby_type( Object ) { |type, val|
|
||||
type, obj_class = YAML.read_type_class( type, Object )
|
||||
YAML.object_maker( obj_class, val )
|
||||
}
|
||||
|
||||
#
|
||||
# Maps: Hash#to_yaml
|
||||
#
|
||||
class Hash
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml_type
|
||||
if self.class == Hash or self.class == YAML::SpecialHash
|
||||
"!map"
|
||||
else
|
||||
"!ruby/hash:#{self.class}"
|
||||
end
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:DocType] = self.class if Hash === opts
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
hash_type = to_yaml_type
|
||||
if not out.options[:ExplicitTypes] and hash_type == "!map"
|
||||
hash_type = ""
|
||||
end
|
||||
out.map( hash_type ) { |map|
|
||||
#
|
||||
# Sort the hash
|
||||
#
|
||||
if out.options[:SortKeys]
|
||||
map.concat( self.sort )
|
||||
else
|
||||
map.concat( self.to_a )
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
hash_proc = Proc.new { |type, val|
|
||||
if Array === val
|
||||
val = Hash.[]( *val ) # Convert the map to a sequence
|
||||
elsif Hash === val
|
||||
type, obj_class = YAML.read_type_class( type, Hash )
|
||||
if obj_class != Hash
|
||||
o = obj_class.new
|
||||
o.update( val )
|
||||
val = o
|
||||
end
|
||||
else
|
||||
raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect
|
||||
end
|
||||
val
|
||||
}
|
||||
YAML.add_builtin_type( /^map/, &hash_proc )
|
||||
YAML.add_ruby_type( Hash, &hash_proc )
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Ruby-specific collection: !ruby/flexhash
|
||||
#
|
||||
class FlexHash < Array
|
||||
def []( k )
|
||||
self.assoc( k ).to_a[1]
|
||||
end
|
||||
def []=( k, *rest )
|
||||
val, set = rest.reverse
|
||||
if ( tmp = self.assoc( k ) ) and not set
|
||||
tmp[1] = val
|
||||
else
|
||||
self << [ k, val ]
|
||||
end
|
||||
val
|
||||
end
|
||||
def has_key?( k )
|
||||
self.assoc( k ) ? true : false
|
||||
end
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out.seq( "!ruby/flexhash" ) { |seq|
|
||||
self.each { |v|
|
||||
if v[1]
|
||||
seq.add( Hash.[]( *v ) )
|
||||
else
|
||||
seq.add( v[0] )
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_ruby_type( :flexhash ) { |type, val|
|
||||
if Array === val
|
||||
p = FlexHash.new
|
||||
val.each { |v|
|
||||
if Hash === v
|
||||
p.concat( v.to_a ) # Convert the map to a sequence
|
||||
else
|
||||
p << [ v, nil ]
|
||||
end
|
||||
}
|
||||
p
|
||||
else
|
||||
raise YAML::Error, "Invalid !ruby/flexhash: " + val.inspect
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Structs: export as a !map
|
||||
#
|
||||
class Struct
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
#
|
||||
# Basic struct is passed as a YAML map
|
||||
#
|
||||
struct_name = self.class.name.gsub( "Struct:", "" )
|
||||
out.map( "!ruby/struct#{struct_name}" ) { |map|
|
||||
self.members.each { |m|
|
||||
map.add( m, self[m] )
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_ruby_type( Struct ) { |type, val|
|
||||
type =~ /^struct:(\w+)/
|
||||
if Hash === val
|
||||
type = $1
|
||||
struct_type = nil
|
||||
struct_def = []
|
||||
struct_name = ""
|
||||
if $1.to_s.length > 1
|
||||
struct_name = $1[0..$1.length]
|
||||
struct_def << struct_name
|
||||
end
|
||||
|
||||
#
|
||||
# Use existing Struct if it exists
|
||||
#
|
||||
begin
|
||||
struct_type = Struct.const_get( struct_name )
|
||||
rescue NameError
|
||||
end
|
||||
if not struct_type
|
||||
struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) )
|
||||
end
|
||||
|
||||
#
|
||||
# Set the Struct properties
|
||||
#
|
||||
st = struct_type.new
|
||||
st.members.each { |m|
|
||||
st.send( "#{m}=", val[m] )
|
||||
}
|
||||
st
|
||||
else
|
||||
raise YAML::Error, "Invalid Ruby Struct: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Sequences: Array#to_yaml
|
||||
#
|
||||
class Array
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml_type
|
||||
if self.class == Array
|
||||
"!seq"
|
||||
else
|
||||
"!ruby/array:#{self.class}"
|
||||
end
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:DocType] = self.class if Hash === opts
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
array_type = to_yaml_type
|
||||
if not out.options[:ExplicitTypes] and array_type == "!seq"
|
||||
array_type = ""
|
||||
end
|
||||
|
||||
out.seq( array_type ) { |seq|
|
||||
seq.concat( self )
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
array_proc = Proc.new { |type, val|
|
||||
if Array === val
|
||||
type, obj_class = YAML.read_type_class( type, Array )
|
||||
if obj_class != Array
|
||||
o = obj_class.new
|
||||
o.concat( val )
|
||||
val = o
|
||||
end
|
||||
val
|
||||
else
|
||||
val.to_a
|
||||
end
|
||||
}
|
||||
YAML.add_builtin_type( /^seq/, &array_proc )
|
||||
YAML.add_ruby_type( Array, &array_proc )
|
||||
|
||||
#
|
||||
# String#to_yaml
|
||||
#
|
||||
class String
|
||||
def is_complex_yaml?
|
||||
( self =~ /\n.+/ ? true : false )
|
||||
end
|
||||
def is_binary_data?
|
||||
( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 )
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
complex = false
|
||||
if self.is_complex_yaml?
|
||||
complex = true
|
||||
elsif opts[:BestWidth].to_i > 0
|
||||
if self.length > opts[:BestWidth] and opts[:UseFold]
|
||||
complex = true
|
||||
end
|
||||
end
|
||||
YAML::quick_emit( complex ? self.id : nil, opts ) { |out|
|
||||
if complex
|
||||
if self.is_binary_data?
|
||||
out.binary_base64( self )
|
||||
else
|
||||
out.node_text( self )
|
||||
end
|
||||
else
|
||||
ostr = if out.options[:KeepValue]
|
||||
self
|
||||
elsif empty?
|
||||
"''"
|
||||
elsif YAML.detect_implicit( self ) != 'str'
|
||||
"\"#{YAML.escape( self )}\""
|
||||
elsif self =~ /#{YAML::ESCAPE_CHAR}|[#{YAML::SPACE_INDICATORS}] |\n|\'/
|
||||
"\"#{YAML.escape( self )}\""
|
||||
elsif self =~ /^[^#{YAML::WORD_CHAR}]/
|
||||
"\"#{YAML.escape( self )}\""
|
||||
else
|
||||
self
|
||||
end
|
||||
out.simple( ostr )
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'str' ) { |type,val| val.to_s }
|
||||
YAML.add_builtin_type( 'binary' ) { |type,val|
|
||||
enctype = "m"
|
||||
if String === val
|
||||
val.gsub( /\s+/, '' ).unpack( enctype )[0]
|
||||
else
|
||||
raise YAML::Error, "Binary data must be represented by a string: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Symbol#to_yaml
|
||||
#
|
||||
class Symbol
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( nil, opts ) { |out|
|
||||
out << "!ruby/sym "
|
||||
self.id2name.to_yaml( :Emitter => out )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
symbol_proc = Proc.new { |type, val|
|
||||
if String === val
|
||||
val.intern
|
||||
else
|
||||
raise YAML::Error, "Invalid Symbol: " + val.inspect
|
||||
end
|
||||
}
|
||||
YAML.add_ruby_type( Symbol, &symbol_proc )
|
||||
YAML.add_ruby_type( :sym, &symbol_proc )
|
||||
|
||||
#
|
||||
# Range#to_yaml
|
||||
#
|
||||
class Range
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( nil, opts ) { |out|
|
||||
out << "!ruby/range "
|
||||
self.inspect.to_yaml( :Emitter => out )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_ruby_type( Range ) { |type, val|
|
||||
if String === val and val =~ /^(.*[^.])(\.{2,3})([^.].*)$/
|
||||
r1, rdots, r2 = $1, $2, $3
|
||||
Range.new( YAML.try_implicit( r1 ), YAML.try_implicit( r2 ), rdots.length == 3 )
|
||||
elsif Hash === val
|
||||
Range.new( val['begin'], val['end'], val['exclude_end?'] )
|
||||
else
|
||||
raise YAML::Error, "Invalid Range: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Make an RegExp
|
||||
#
|
||||
class Regexp
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( nil, opts ) { |out|
|
||||
out << "!ruby/regexp "
|
||||
self.inspect.to_yaml( :Emitter => out )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
regexp_proc = Proc.new { |type, val|
|
||||
if String === val and val =~ /^\/(.*)\/([mix]*)$/
|
||||
val = { 'REGEXP' => $1, 'MODIFIERS' => $2 }
|
||||
end
|
||||
if Hash === val
|
||||
mods = nil
|
||||
unless val['MODIFIERS'].to_s.empty?
|
||||
mods = 0x00
|
||||
if val['MODIFIERS'].include?( 'x' )
|
||||
mods |= Regexp::EXTENDED
|
||||
elsif val['MODIFIERS'].include?( 'i' )
|
||||
mods |= Regexp::IGNORECASE
|
||||
elsif val['MODIFIERS'].include?( 'm' )
|
||||
mods |= Regexp::POSIXLINE
|
||||
end
|
||||
end
|
||||
Regexp::compile( val['REGEXP'], mods )
|
||||
else
|
||||
raise YAML::Error, "Invalid Regular expression: " + val.inspect
|
||||
end
|
||||
}
|
||||
YAML.add_domain_type( "perl.yaml.org,2002", /^regexp/, ®exp_proc )
|
||||
YAML.add_ruby_type( Regexp, ®exp_proc )
|
||||
|
||||
#
|
||||
# Emit a Time object as an ISO 8601 timestamp
|
||||
#
|
||||
class Time
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( nil, opts ) { |out|
|
||||
tz = "Z"
|
||||
# from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
|
||||
unless self.utc?
|
||||
utc_same_instant = self.dup.utc
|
||||
utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
|
||||
difference_to_utc = utc_same_writing - utc_same_instant
|
||||
if (difference_to_utc < 0)
|
||||
difference_sign = '-'
|
||||
absolute_difference = -difference_to_utc
|
||||
else
|
||||
difference_sign = '+'
|
||||
absolute_difference = difference_to_utc
|
||||
end
|
||||
difference_minutes = (absolute_difference/60).round
|
||||
tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
|
||||
end
|
||||
( self.strftime( "%Y-%m-%d %H:%M:%S." ) +
|
||||
"%06d %s" % [usec, tz] ).
|
||||
to_yaml( :Emitter => out, :KeepValue => true )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'time' ) { |type, val|
|
||||
if val =~ /\A(\d{4})\-(\d{1,2})\-(\d{1,2})[Tt](\d{2})\:(\d{2})\:(\d{2})(\.\d{1,2})?(Z|[-+][0-9][0-9](?:\:[0-9][0-9])?)\Z/
|
||||
YAML.mktime( *$~.to_a[1,8] )
|
||||
elsif val =~ /\A(\d{4})\-(\d{1,2})\-(\d{1,2})[ \t]+(\d{2})\:(\d{2})\:(\d{2})(\.\d+)?[ \t]+(Z|[-+][0-9][0-9](?:\:[0-9][0-9])?)\Z/
|
||||
YAML.mktime( *$~.to_a[1,8] )
|
||||
elsif val =~ /\A(\d{4})\-(\d{1,2})\-(\d{1,2})[ \t]+(\d{2})\:(\d{2})\:(\d{2})(\.\d{1,2})?\Z/
|
||||
YAML.mktime( *$~.to_a[1,7] )
|
||||
elsif val =~ /\A(\d{4})\-(\d{1,2})\-(\d{1,2})\Z/
|
||||
Date.new($1.to_i, $2.to_i, $3.to_i)
|
||||
elsif type == :Implicit
|
||||
:InvalidType
|
||||
else
|
||||
raise YAML::TypeError, "Invalid !time string: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Emit a Date object as a simple implicit
|
||||
#
|
||||
class Date
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:KeepValue] = true
|
||||
self.to_s.to_yaml( opts )
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Send Integer, Booleans, NilClass to String
|
||||
#
|
||||
class Numeric
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
str = self.to_s
|
||||
if str == "Infinity"
|
||||
str = ".Inf"
|
||||
elsif str == "-Infinity"
|
||||
str = "-.Inf"
|
||||
elsif str == "NaN"
|
||||
str = ".NaN"
|
||||
end
|
||||
opts[:KeepValue] = true
|
||||
str.to_yaml( opts )
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'float' ) { |type, val|
|
||||
if val =~ /\A[-+]?[\d][\d,]*\.[\d,]*[eE][-+][0-9]+\Z/ # Float (exponential)
|
||||
$&.tr( ',', '' ).to_f
|
||||
elsif val =~ /\A[-+]?[\d][\d,]*\.[\d,]*\Z/ # Float (fixed)
|
||||
$&.tr( ',', '' ).to_f
|
||||
elsif val =~ /\A([-+]?)\.(inf|Inf|INF)\Z/ # Float (english)
|
||||
( $1 == "-" ? -1.0/0.0 : 1.0/0.0 )
|
||||
elsif val =~ /\A\.(nan|NaN|NAN)\Z/
|
||||
0.0/0.0
|
||||
elsif type == :Implicit
|
||||
:InvalidType
|
||||
else
|
||||
val.to_f
|
||||
end
|
||||
}
|
||||
|
||||
YAML.add_builtin_type( 'int' ) { |type, val|
|
||||
if val =~ /\A[-+]?0[0-7,]+\Z/ # Integer (octal)
|
||||
$&.oct
|
||||
elsif val =~ /\A[-+]?0x[0-9a-fA-F,]+\Z/ # Integer (hex)
|
||||
$&.hex
|
||||
elsif val =~ /\A[-+]?\d[\d,]*\Z/ # Integer (canonical)
|
||||
$&.tr( ',', '' ).to_i
|
||||
elsif val =~ /\A([-+]?)(\d[\d,]*(?::[0-5]?[0-9])+)\Z/
|
||||
sign = ( $1 == '-' ? -1 : 1 )
|
||||
digits = $2.split( /:/ ).collect { |x| x.to_i }
|
||||
val = 0; digits.each { |x| val = ( val * 60 ) + x }; val *= sign
|
||||
elsif type == :Implicit
|
||||
:InvalidType
|
||||
else
|
||||
val.to_i
|
||||
end
|
||||
}
|
||||
|
||||
class TrueClass
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:KeepValue] = true
|
||||
"true".to_yaml( opts )
|
||||
end
|
||||
end
|
||||
|
||||
class FalseClass
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:KeepValue] = true
|
||||
"false".to_yaml( opts )
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'bool' ) { |type, val|
|
||||
if val =~ /\A(\+|true|True|TRUE|yes|Yes|YES|on|On|ON)\Z/
|
||||
true
|
||||
elsif val =~ /\A(\-|false|False|FALSE|no|No|NO|off|Off|OFF)\Z/
|
||||
false
|
||||
elsif type == :Implicit
|
||||
:InvalidType
|
||||
else
|
||||
raise YAML::TypeError, "Invalid !bool string: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
||||
class NilClass
|
||||
def is_complex_yaml?
|
||||
false
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:KeepValue] = true
|
||||
"".to_yaml( opts )
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'null' ) { |type, val|
|
||||
if val =~ /\A(\~|null|Null|NULL)\Z/
|
||||
nil
|
||||
elsif val.empty?
|
||||
nil
|
||||
elsif type == :Implicit
|
||||
:InvalidType
|
||||
else
|
||||
raise YAML::TypeError, "Invalid !null string: " + val.inspect
|
||||
end
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#
|
||||
# YAML::Store
|
||||
#
|
||||
require 'yaml'
|
||||
require 'pstore'
|
||||
|
||||
module YAML
|
||||
|
||||
class Store < PStore
|
||||
#
|
||||
# Constructor
|
||||
#
|
||||
def initialize( *o )
|
||||
@opt = YAML::DEFAULTS.dup
|
||||
if String === o.first
|
||||
super(o.pop)
|
||||
end
|
||||
if o.last.is_a? Hash
|
||||
@opt.update(o.pop)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Override Pstore#transaction
|
||||
#
|
||||
def transaction
|
||||
raise YAML::Error, "nested transaction" if @transaction
|
||||
raise YAML::Error, "no filename for transaction" unless @filename
|
||||
begin
|
||||
@transaction = true
|
||||
value = nil
|
||||
backup = @filename+"~"
|
||||
if File::exist?(@filename)
|
||||
file = File::open(@filename, "rb+")
|
||||
orig = true
|
||||
else
|
||||
@table = {}
|
||||
file = File::open(@filename, "wb+")
|
||||
file.write( @table.to_yaml( @opt ) )
|
||||
end
|
||||
file.flock(File::LOCK_EX)
|
||||
if orig
|
||||
File::copy @filename, backup
|
||||
@table = YAML::load( file )
|
||||
end
|
||||
begin
|
||||
catch(:pstore_abort_transaction) do
|
||||
value = yield(self)
|
||||
end
|
||||
rescue Exception
|
||||
@abort = true
|
||||
raise
|
||||
ensure
|
||||
unless @abort
|
||||
begin
|
||||
file.rewind
|
||||
file.write( @table.to_yaml( @opt ) )
|
||||
file.truncate(file.pos)
|
||||
rescue
|
||||
File::rename backup, @filename if File::exist?(backup)
|
||||
raise
|
||||
end
|
||||
end
|
||||
@abort = false
|
||||
end
|
||||
ensure
|
||||
@table = nil
|
||||
@transaction = false
|
||||
file.close if file
|
||||
end
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
module YAML
|
||||
|
||||
#
|
||||
# YAML::Stream -- for emitting many documents
|
||||
#
|
||||
class Stream
|
||||
|
||||
attr_accessor :documents, :options
|
||||
|
||||
def initialize( opts = {} )
|
||||
@options = opts
|
||||
@documents = []
|
||||
end
|
||||
|
||||
def []( i )
|
||||
@documents[ i ]
|
||||
end
|
||||
|
||||
def add( doc )
|
||||
@documents << doc
|
||||
end
|
||||
|
||||
def edit( doc_num, doc )
|
||||
@documents[ doc_num ] = doc
|
||||
end
|
||||
|
||||
def emit
|
||||
opts = @options.dup
|
||||
opts[:UseHeader] = true if @documents.length > 1
|
||||
ct = 0
|
||||
out = Emitter.new( opts )
|
||||
@documents.each { |v|
|
||||
if ct > 0
|
||||
out << "\n--- "
|
||||
end
|
||||
v.to_yaml( :Emitter => out )
|
||||
ct += 1
|
||||
}
|
||||
out.end_object
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
#
|
||||
# Limited StringIO if no core lib is available
|
||||
#
|
||||
begin
|
||||
require 'stringio'
|
||||
rescue LoadError
|
||||
# StringIO based on code by MoonWolf
|
||||
class StringIO
|
||||
def initialize(string="")
|
||||
@string=string
|
||||
@pos=0
|
||||
@eof=(string.size==0)
|
||||
end
|
||||
def pos
|
||||
@pos
|
||||
end
|
||||
def eof
|
||||
@eof
|
||||
end
|
||||
alias eof? eof
|
||||
def readline(rs=$/)
|
||||
if @eof
|
||||
raise EOFError
|
||||
else
|
||||
if p = @string[@pos..-1]=~rs
|
||||
line = @string[@pos,p+1]
|
||||
else
|
||||
line = @string[@pos..-1]
|
||||
end
|
||||
@pos+=line.size
|
||||
@eof =true if @pos==@string.size
|
||||
$_ = line
|
||||
end
|
||||
end
|
||||
def rewind
|
||||
seek(0,0)
|
||||
end
|
||||
def seek(offset,whence)
|
||||
case whence
|
||||
when 0
|
||||
@pos=offset
|
||||
when 1
|
||||
@pos+=offset
|
||||
when 2
|
||||
@pos=@string.size+offset
|
||||
end
|
||||
@eof=(@pos>=@string.size)
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Class method for creating streams
|
||||
#
|
||||
def YAML.make_stream( io )
|
||||
if String === io
|
||||
io = StringIO.new( io )
|
||||
elsif not IO === io
|
||||
raise YAML::Error, "YAML stream must be an IO or String object."
|
||||
end
|
||||
if YAML::unicode
|
||||
def io.readline
|
||||
YAML.utf_to_internal( readline( @ln_sep ), @utf_encoding )
|
||||
end
|
||||
def io.check_unicode
|
||||
@utf_encoding = YAML.sniff_encoding( read( 4 ) )
|
||||
@ln_sep = YAML.enc_separator( @utf_encoding )
|
||||
seek( -4, IO::SEEK_CUR )
|
||||
end
|
||||
def io.utf_encoding
|
||||
@utf_encoding
|
||||
end
|
||||
io.check_unicode
|
||||
else
|
||||
def io.utf_encoding
|
||||
:None
|
||||
end
|
||||
end
|
||||
io
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# YAML::Syck module
|
||||
# .. glues syck and yaml.rb together ..
|
||||
#
|
||||
require 'syck'
|
||||
require 'yaml/basenode'
|
||||
|
||||
module YAML
|
||||
module Syck
|
||||
|
||||
#
|
||||
# Mixin BaseNode functionality
|
||||
#
|
||||
class Node
|
||||
include YAML::BaseNode
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,195 @@
|
|||
#
|
||||
# Classes required by the full core typeset
|
||||
#
|
||||
module YAML
|
||||
|
||||
#
|
||||
# Default private type
|
||||
#
|
||||
class PrivateType
|
||||
attr_accessor :type_id, :value
|
||||
def initialize( type, val )
|
||||
@type_id = type; @value = val
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out << " !!#{@type_id}"
|
||||
value.to_yaml( :Emitter => out )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Default domain type
|
||||
#
|
||||
class DomainType
|
||||
attr_accessor :domain, :type_id, :value
|
||||
def initialize( domain, type, val )
|
||||
@domain = domain; @type_id = type; @value = val
|
||||
end
|
||||
def to_yaml_type
|
||||
dom = @domain.dup
|
||||
if dom =~ /\.yaml\.org,2002$/
|
||||
dom = $`
|
||||
end
|
||||
"#{dom}/#{@type_id}"
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out << " !#{to_yaml_type} "
|
||||
value.to_yaml( :Emitter => out )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# YAML Hash class to support comments and defaults
|
||||
#
|
||||
class SpecialHash < Kernel::Hash
|
||||
attr_accessor :default
|
||||
def inspect
|
||||
self.default.to_s
|
||||
end
|
||||
def to_s
|
||||
self.default.to_s
|
||||
end
|
||||
def update( h )
|
||||
if YAML::SpecialHash === h
|
||||
@default = h.default if h.default
|
||||
end
|
||||
super( h )
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
opts[:DefaultKey] = self.default
|
||||
super( opts )
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Builtin collection: !omap
|
||||
#
|
||||
class Omap < Array
|
||||
def self.[]( *vals )
|
||||
o = Omap.new
|
||||
0.step( vals.length - 1, 2 ) { |i|
|
||||
o[vals[i]] = vals[i+1]
|
||||
}
|
||||
o
|
||||
end
|
||||
def []( k )
|
||||
self.assoc( k ).to_a[1]
|
||||
end
|
||||
def []=( k, *rest )
|
||||
val, set = rest.reverse
|
||||
if ( tmp = self.assoc( k ) ) and not set
|
||||
tmp[1] = val
|
||||
else
|
||||
self << [ k, val ]
|
||||
end
|
||||
val
|
||||
end
|
||||
def has_key?( k )
|
||||
self.assoc( k ) ? true : false
|
||||
end
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out.seq( "!omap" ) { |seq|
|
||||
self.each { |v|
|
||||
seq.add( Hash[ *v ] )
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( "omap" ) { |type, val|
|
||||
if Array === val
|
||||
p = Omap.new
|
||||
val.each { |v|
|
||||
if Hash === v
|
||||
p.concat( v.to_a ) # Convert the map to a sequence
|
||||
else
|
||||
raise YAML::Error, "Invalid !omap entry: " + val.inspect
|
||||
end
|
||||
}
|
||||
else
|
||||
raise YAML::Error, "Invalid !omap: " + val.inspect
|
||||
end
|
||||
p
|
||||
}
|
||||
|
||||
#
|
||||
# Builtin collection: !pairs
|
||||
#
|
||||
class Pairs < Array
|
||||
def self.[]( *vals )
|
||||
p = Pairs.new
|
||||
0.step( vals.length - 1, 2 ) { |i|
|
||||
p[vals[i]] = vals[i+1]
|
||||
}
|
||||
p
|
||||
end
|
||||
def []( k )
|
||||
self.assoc( k ).to_a
|
||||
end
|
||||
def []=( k, val )
|
||||
self << [ k, val ]
|
||||
val
|
||||
end
|
||||
def has_key?( k )
|
||||
self.assoc( k ) ? true : false
|
||||
end
|
||||
def is_complex_yaml?
|
||||
true
|
||||
end
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( self.id, opts ) { |out|
|
||||
out.seq( "!pairs" ) { |seq|
|
||||
self.each { |v|
|
||||
seq.add( Hash[ *v ] )
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( "pairs" ) { |type, val|
|
||||
if Array === val
|
||||
p = Pairs.new
|
||||
val.each { |v|
|
||||
if Hash === v
|
||||
p.concat( v.to_a ) # Convert the map to a sequence
|
||||
else
|
||||
raise YAML::Error, "Invalid !pairs entry: " + val.inspect
|
||||
end
|
||||
}
|
||||
else
|
||||
raise YAML::Error, "Invalid !pairs: " + val.inspect
|
||||
end
|
||||
p
|
||||
}
|
||||
|
||||
#
|
||||
# Builtin collection: !set
|
||||
#
|
||||
class Set < Hash
|
||||
def to_yaml_type
|
||||
"!set"
|
||||
end
|
||||
end
|
||||
|
||||
YAML.add_builtin_type( 'set' ) { |type, val|
|
||||
if Array === val
|
||||
val = Set[ *val ]
|
||||
elsif Hash === val
|
||||
Set[ val ]
|
||||
else
|
||||
raise YAML::Error, "Invalid map explicitly tagged !map: " + val.inspect
|
||||
end
|
||||
val
|
||||
}
|
||||
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# YAML::YamlNode class
|
||||
#
|
||||
require 'yaml/basenode'
|
||||
|
||||
module YAML
|
||||
|
||||
#
|
||||
# YAML Generic Model container
|
||||
#
|
||||
class YamlNode
|
||||
include BaseNode
|
||||
attr_accessor :kind, :type_id, :value, :anchor
|
||||
def initialize( t, v )
|
||||
@type_id = t
|
||||
if Hash === v
|
||||
@kind = 'map'
|
||||
@value = {}
|
||||
v.each { |k,v|
|
||||
@value[ k.transform ] = [ k, v ]
|
||||
}
|
||||
elsif Array === v
|
||||
@kind = 'seq'
|
||||
@value = v
|
||||
elsif String === v
|
||||
@kind = 'scalar'
|
||||
@value = v
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Transform this node fully into a native type
|
||||
#
|
||||
def transform
|
||||
t = nil
|
||||
if @value.is_a? Hash
|
||||
t = {}
|
||||
@value.each { |k,v|
|
||||
t[ k ] = v[1].transform
|
||||
}
|
||||
elsif @value.is_a? Array
|
||||
t = []
|
||||
@value.each { |v|
|
||||
t.push v.transform
|
||||
}
|
||||
else
|
||||
t = @value
|
||||
end
|
||||
YAML.transfer_method( @type_id, t )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
#
|
||||
# YAML::YPath
|
||||
#
|
||||
|
||||
module YAML
|
||||
|
||||
class YPath
|
||||
attr_accessor :segments, :predicates, :flags
|
||||
def initialize( str )
|
||||
@segments = []
|
||||
@predicates = []
|
||||
@flags = nil
|
||||
while str =~ /^\/?(\/|[^\/[]+)(?:\[([^\]]+)\])?/
|
||||
@segments.push $1
|
||||
@predicates.push $2
|
||||
str = $'
|
||||
end
|
||||
unless str.to_s.empty?
|
||||
@segments += str.split( "/" )
|
||||
end
|
||||
if @segments.length == 0
|
||||
@segments.push "."
|
||||
end
|
||||
end
|
||||
def YPath.each_path( str )
|
||||
#
|
||||
# Find choices
|
||||
#
|
||||
paths = []
|
||||
str = "(#{ str })"
|
||||
while str.sub!( /\(([^()]+)\)/, "\n#{ paths.length }\n" )
|
||||
paths.push $1.split( '|' )
|
||||
end
|
||||
|
||||
#
|
||||
# Construct all possible paths
|
||||
#
|
||||
all = [ str ]
|
||||
( paths.length - 1 ).downto( 0 ) do |i|
|
||||
all = all.collect do |a|
|
||||
paths[i].collect do |p|
|
||||
a.gsub( /\n#{ i }\n/, p )
|
||||
end
|
||||
end.flatten.uniq
|
||||
end
|
||||
all.collect do |path|
|
||||
yield YPath.new( path )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Загрузка…
Ссылка в новой задаче