summaryrefslogtreecommitdiff
path: root/ext/syck
diff options
context:
space:
mode:
authorwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-07-11 22:52:14 +0000
committerwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-07-11 22:52:14 +0000
commita1e257ec48911d3ca1aaeda0127061c244f36147 (patch)
treeb77a31d1f26f6f313ee33af850fc539a6e149f39 /ext/syck
parent30399f6c758c85ac9794d4298ee2b51426a144bc (diff)
* ext/syck/emitter.c: new emitter code.
* ext/syck/rubyext.c: Emitter class. * lib/yaml.rb: Load Syck emitter, if available. * lib/yaml/stream.rb: ditto. * lib/yaml/baseemitter.rb: underlying class for all emitters. * lib/yaml/rubytypes.rb: use BaseEmitter abstraction. * lib/yaml/emitter.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4066 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/syck')
-rw-r--r--ext/syck/rubyext.c173
-rw-r--r--ext/syck/syck.c37
-rw-r--r--ext/syck/syck.h104
3 files changed, 285 insertions, 29 deletions
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index 724dd7a..6a26cd4 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -40,7 +40,7 @@ typedef struct RVALUE {
static ID s_new, s_utc, s_at, s_to_f, s_read, s_binmode, s_call, s_transfer, s_update, s_dup, s_match;
static VALUE sym_model, sym_generic;
static VALUE sym_scalar, sym_seq, sym_map;
-VALUE cDate, cParser, cLoader, cNode, cPrivateType, cDomainType, cBadAlias, cMergeKey;
+VALUE cDate, cParser, cLoader, cNode, cPrivateType, cDomainType, cBadAlias, cMergeKey, cEmitter;
VALUE oDefaultLoader;
/*
@@ -57,6 +57,7 @@ SYMID rb_syck_parse_handler _((SyckParser *, SyckNode *));
SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
void rb_syck_err_handler _((SyckParser *, char *));
SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
+void rb_syck_output_handler _((SyckEmitter *, char *, long));
struct parser_xtra {
VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
@@ -1016,6 +1017,162 @@ syck_node_transform( self )
}
/*
+ * Handle output from the emitter
+ */
+void
+rb_syck_output_handler( emitter, str, len )
+ SyckEmitter *emitter;
+ char *str;
+ long len;
+{
+ rb_str_cat( (VALUE)emitter->bonus, str, len );
+}
+
+/*
+ * Mark emitter values.
+ */
+static void
+syck_mark_emitter(emitter)
+ SyckEmitter *emitter;
+{
+ rb_gc_mark(emitter->ignore_id);
+}
+
+/*
+ * YAML::Syck::Emitter.new
+ */
+VALUE
+syck_emitter_new(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ VALUE pobj, options, init_argv[1];
+ SyckEmitter *emitter = syck_new_emitter();
+ syck_emitter_ignore_id( emitter, Qnil );
+ syck_emitter_handler( emitter, rb_syck_output_handler );
+
+ emitter->bonus = (void *)rb_str_new2( "" );
+
+ rb_scan_args(argc, argv, "01", &options);
+ pobj = Data_Wrap_Struct( class, syck_mark_emitter, syck_free_emitter, emitter );
+
+ 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::Emitter.initialize( options )
+ */
+static VALUE
+syck_emitter_initialize( self, options )
+ VALUE self, options;
+{
+ rb_iv_set(self, "@options", options);
+ return self;
+}
+
+/*
+ * YAML::Syck::Emitter.level
+ */
+VALUE
+syck_emitter_level_m( self )
+ VALUE self;
+{
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ return LONG2NUM( emitter->level );
+}
+
+/*
+ * YAML::Syck::Emitter.flush
+ */
+VALUE
+syck_emitter_flush_m( self )
+ VALUE self;
+{
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ syck_emitter_flush( emitter );
+ return self;
+}
+
+/*
+ * YAML::Syck::Emitter.write( str )
+ */
+VALUE
+syck_emitter_write_m( self, str )
+ VALUE str;
+{
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ syck_emitter_write( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
+ return self;
+}
+
+/*
+ * YAML::Syck::Emitter.simple( str )
+ */
+VALUE
+syck_emitter_simple_write( self, str )
+ VALUE str;
+{
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ syck_emitter_simple( emitter, RSTRING(str)->ptr, RSTRING(str)->len );
+ return self;
+}
+
+/*
+ * YAML::Syck::Emitter.start_object( object_id )
+ */
+VALUE
+syck_emitter_start_object( self, oid )
+ VALUE self, oid;
+{
+ char *anchor_name;
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ anchor_name = syck_emitter_start_obj( emitter, oid );
+
+ if ( anchor_name == NULL )
+ {
+ return Qnil;
+ }
+
+ return rb_str_new2( anchor_name );
+}
+
+/*
+ * YAML::Syck::Emitter.end_object( object_id )
+ */
+VALUE
+syck_emitter_end_object( self, oid )
+ VALUE self, oid;
+{
+ SyckEmitter *emitter;
+
+ Data_Get_Struct(self, SyckEmitter, emitter);
+ syck_emitter_end_obj( emitter );
+
+ if ( emitter->level < 0 )
+ {
+ syck_emitter_flush( emitter );
+ }
+ return (VALUE)emitter->bonus;
+}
+
+/*
* Initialize Syck extension
*/
void
@@ -1118,5 +1275,19 @@ Init_syck()
* Define YAML::Syck::MergeKey class
*/
cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
+
+ /*
+ * Define YAML::Syck::Emitter class
+ */
+ cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
+ rb_define_singleton_method( cEmitter, "new", syck_emitter_new, -1 );
+ rb_define_method( cEmitter, "initialize", syck_emitter_initialize, 1 );
+ rb_define_method( cEmitter, "level", syck_emitter_level_m, 0 );
+ rb_define_method( cEmitter, "write", syck_emitter_write_m, 1 );
+ rb_define_method( cEmitter, "<<", syck_emitter_write_m, 1 );
+ rb_define_method( cEmitter, "simple", syck_emitter_simple_write, 1 );
+ rb_define_method( cEmitter, "flush", syck_emitter_flush_m, 0 );
+ rb_define_method( cEmitter, "start_object", syck_emitter_start_object, 1 );
+ rb_define_method( cEmitter, "end_object", syck_emitter_end_object, 0 );
}
diff --git a/ext/syck/syck.c b/ext/syck/syck.c
index a7955b4..4b7be32 100644
--- a/ext/syck/syck.c
+++ b/ext/syck/syck.c
@@ -11,10 +11,6 @@
#include "syck.h"
-#define SYCK_YAML_MAJOR 1
-#define SYCK_YAML_MINOR 0
-#define SYCK_BUFFERSIZE 262144
-
void syck_parser_pop_level( SyckParser * );
/*
@@ -30,6 +26,9 @@ syck_assert( char *file_name, unsigned line_num )
abort();
}
+/*
+ * Allocates and copies a string
+ */
char *
syck_strndup( char *buf, long len )
{
@@ -40,7 +39,7 @@ syck_strndup( char *buf, long len )
}
/*
- * Default IO functions
+ * Default FILE IO function
*/
long
syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
@@ -52,18 +51,15 @@ syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
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;
}
+/*
+ * Default string IO function
+ */
long
syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
{
@@ -95,15 +91,9 @@ syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
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;
}
@@ -150,6 +140,9 @@ syck_parser_reset_cursor( SyckParser *p )
p->force_token = 0;
}
+/*
+ * Value to return on a parse error
+ */
void
syck_parser_set_root_on_error( SyckParser *p, SYMID roer )
{
@@ -212,7 +205,7 @@ syck_st_free( SyckParser *p )
{
/*
* Free the adhoc symbol table
- */
+ */
if ( p->syms != NULL )
{
st_free_table( p->syms );
@@ -410,10 +403,6 @@ syck_move_tokens( SyckParser *p )
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 );
diff --git a/ext/syck/syck.h b/ext/syck/syck.h
index 20ad18a..259a4cd 100644
--- a/ext/syck/syck.h
+++ b/ext/syck/syck.h
@@ -10,6 +10,9 @@
#ifndef SYCK_H
#define SYCK_H
+#define SYCK_YAML_MAJOR 1
+#define SYCK_YAML_MINOR 0
+
#define SYCK_VERSION "0.35"
#define YAML_DOMAIN "yaml.org,2002"
@@ -43,6 +46,7 @@ extern "C" {
#endif
#define ALLOC_CT 8
+#define SYCK_BUFFERSIZE 262144
#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))
@@ -66,11 +70,7 @@ extern "C" {
*/
#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,
@@ -83,6 +83,9 @@ enum map_part {
map_value
};
+/*
+ * Node metadata struct
+ */
struct _syck_node {
/* Symbol table ID */
SYMID id;
@@ -119,6 +122,11 @@ struct _syck_node {
/*
* Parser definitions
*/
+typedef struct _syck_parser SyckParser;
+typedef struct _syck_file SyckIoFile;
+typedef struct _syck_str SyckIoStr;
+typedef struct _syck_level SyckLevel;
+
typedef SYMID (*SyckNodeHandler)(SyckParser *, SyckNode *);
typedef void (*SyckErrorHandler)(SyckParser *, char *);
typedef SyckNode * (*SyckBadAnchorHandler)(SyckParser *, char *);
@@ -142,6 +150,9 @@ enum syck_level_status {
syck_lvl_pause
};
+/*
+ * Parser struct
+ */
struct _syck_parser {
/* Root node */
SYMID root, root_on_error;
@@ -193,6 +204,82 @@ struct _syck_parser {
};
/*
+ * Emitter definitions
+ */
+typedef struct _syck_emitter SyckEmitter;
+typedef struct _syck_emitter_node SyckEmitterNode;
+
+typedef void (*SyckOutputHandler)(SyckEmitter *, char *, long);
+
+enum doc_stage {
+ doc_open,
+ doc_need_header,
+ doc_processing
+};
+
+enum block_styles {
+ block_arbitrary,
+ block_fold,
+ block_literal
+};
+
+/*
+ * Emitter struct
+ */
+struct _syck_emitter {
+ /* Headerless doc flag */
+ int headless;
+ /* Sequence map shortcut flag */
+ int seq_map;
+ /* Force header? */
+ int use_header;
+ /* Force version? */
+ int use_version;
+ /* Sort hash keys */
+ int sort_keys;
+ /* Anchor format */
+ char *anchor_format;
+ /* Explicit typing on all collections? */
+ int explicit_typing;
+ /* Best width on folded scalars */
+ int best_width;
+ /* Use literal[1] or folded[2] blocks on all text? */
+ enum block_styles block_style;
+ /* Stage of written document */
+ enum doc_stage stage;
+ /* Level counter */
+ int level;
+ /* Default indentation */
+ int indent;
+ /* Object ignore ID */
+ SYMID ignore_id;
+ /* Symbol table for anchors */
+ st_table *markers, *anchors;
+ /* Custom buffer size */
+ size_t bufsize;
+ /* Buffer */
+ char *buffer, *marker;
+ /* Absolute position of the buffer */
+ long bufpos;
+ /* Handler for output */
+ SyckOutputHandler handler;
+ /* Pointer for extension's use */
+ void *bonus;
+};
+
+/*
+ * Emitter node metadata struct
+ */
+struct _syck_emitter_node {
+ /* Node buffer position */
+ long pos;
+ /* Current indent */
+ long indent;
+ /* Collection? */
+ int is_shortcut;
+};
+
+/*
* Handler prototypes
*/
SYMID syck_hdlr_add_node( SyckParser *, SyckNode * );
@@ -215,6 +302,15 @@ char *syck_match_implicit( char *, size_t );
char *syck_strndup( char *, long );
long syck_io_file_read( char *, SyckIoFile *, long, long );
long syck_io_str_read( char *, SyckIoStr *, long, long );
+SyckEmitter *syck_new_emitter();
+void syck_emitter_ignore_id( SyckEmitter *, SYMID );
+void syck_emitter_handler( SyckEmitter *, SyckOutputHandler );
+void syck_free_emitter( SyckEmitter * );
+void syck_emitter_clear( SyckEmitter * );
+void syck_emitter_write( SyckEmitter *, char *, long );
+void syck_emitter_flush( SyckEmitter * );
+char *syck_emitter_start_obj( SyckEmitter *, SYMID );
+void syck_emitter_end_obj( SyckEmitter * );
SyckParser *syck_new_parser();
void syck_free_parser( SyckParser * );
void syck_parser_set_root_on_error( SyckParser *, SYMID );