mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* 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
This commit is contained in:
		
							parent
							
								
									30399f6c75
								
							
						
					
					
						commit
						a1e257ec48
					
				
					 9 changed files with 359 additions and 271 deletions
				
			
		
							
								
								
									
										16
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,3 +1,19 @@ | |||
| Sat Jul 12 04:43:57 2003  why the lucky stiff  <ruby-cvs@whytheluckystiff.net> | ||||
| 
 | ||||
|     * 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. | ||||
| 
 | ||||
| Sat Jul 12 01:21:54 2003  Nobuyoshi Nakada  <nobu.nokada@softhome.net> | ||||
| 
 | ||||
| 	* eval.c (avalue_to_svalue): typo. | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  | @ -1015,6 +1016,162 @@ syck_node_transform( self ) | |||
|     return rb_funcall( oDefaultLoader, s_transfer, 2, type_id, t ); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  */ | ||||
|  | @ -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 ); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 ); | ||||
|  |  | |||
							
								
								
									
										104
									
								
								ext/syck/syck.h
									
										
									
									
									
								
							
							
						
						
									
										104
									
								
								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; | ||||
|  | @ -192,6 +203,82 @@ struct _syck_parser { | |||
|     void *bonus; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  */ | ||||
|  | @ -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 ); | ||||
|  |  | |||
							
								
								
									
										37
									
								
								lib/yaml.rb
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								lib/yaml.rb
									
										
									
									
									
								
							|  | @ -12,15 +12,26 @@ module YAML | |||
|         require 'yaml/syck' | ||||
|         @@parser = YAML::Syck::Parser | ||||
|         @@loader = YAML::Syck::DefaultLoader | ||||
|         @@emitter = YAML::Syck::Emitter | ||||
|     rescue LoadError | ||||
|         require 'yaml/parser' | ||||
|         @@parser = YAML::Parser | ||||
|         @@loader = YAML::DefaultLoader | ||||
|         require 'yaml/emitter' | ||||
|         @@emitter = YAML::Emitter | ||||
|     end | ||||
|     require 'yaml/emitter' | ||||
|     require 'yaml/loader' | ||||
|     require 'yaml/stream' | ||||
| 
 | ||||
| 	# | ||||
| 	# Load a single document from the current stream | ||||
| 	# | ||||
| 	def YAML.dump( obj, io = nil ) | ||||
|         io ||= "" | ||||
|         io << obj.to_yaml | ||||
|         io | ||||
| 	end | ||||
| 
 | ||||
| 	# | ||||
| 	# Load a single document from the current stream | ||||
| 	# | ||||
|  | @ -158,6 +169,30 @@ module YAML | |||
|         end | ||||
|     end | ||||
| 
 | ||||
| 	# | ||||
| 	# Allocate an Emitter if needed | ||||
| 	# | ||||
| 	def YAML.quick_emit( oid, opts = {}, &e ) | ||||
| 		old_opt = nil | ||||
| 		if opts[:Emitter].is_a? @@emitter | ||||
| 			out = opts.delete( :Emitter ) | ||||
| 			old_opt = out.options.dup | ||||
| 			out.options.update( opts ) | ||||
| 		else | ||||
| 			out = @@emitter.new( opts ) | ||||
| 		end | ||||
|         aidx = out.start_object( oid ) | ||||
|         if aidx | ||||
|             out.simple( "*#{ aidx }" ) | ||||
|         else | ||||
|             e.call( out ) | ||||
|         end | ||||
| 		if old_opt.is_a? Hash | ||||
| 			out.options = old_opt | ||||
| 		end  | ||||
| 		out.end_object | ||||
| 	end | ||||
| 	 | ||||
| end | ||||
| 
 | ||||
| require 'yaml/rubytypes' | ||||
|  |  | |||
|  | @ -2,9 +2,8 @@ | |||
| # Output classes and methods | ||||
| # | ||||
| 
 | ||||
| require 'yaml/constants' | ||||
| require 'yaml/baseemitter' | ||||
| require 'yaml/encoding' | ||||
| require 'yaml/error' | ||||
| 
 | ||||
| module YAML | ||||
| 
 | ||||
|  | @ -13,7 +12,11 @@ module YAML | |||
| 	# | ||||
|      | ||||
| 	class Emitter | ||||
| 
 | ||||
|         include BaseEmitter | ||||
| 
 | ||||
| 		attr_accessor :options | ||||
| 
 | ||||
| 		def initialize( opts ) | ||||
| 			opts = {} if opts.class != Hash | ||||
| 			@options = YAML::DEFAULTS.dup.update( opts ) | ||||
|  | @ -30,6 +33,10 @@ module YAML | |||
| 			@buffer = [] | ||||
| 		end | ||||
| 
 | ||||
|         def level | ||||
|             @level | ||||
|         end | ||||
| 
 | ||||
| 		# | ||||
| 		# Version string | ||||
| 		# | ||||
|  | @ -48,201 +55,6 @@ module YAML | |||
|             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 = '>' ) | ||||
|             @seq_map = false | ||||
| 			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 ) | ||||
|             @seq_map = false | ||||
|             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 << "{}" | ||||
|                 @seq_map = false | ||||
| 			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 ) | ||||
|             @seq_map = false | ||||
|             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 | ||||
| 		# | ||||
|  | @ -291,44 +103,5 @@ module YAML | |||
| 		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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -53,14 +53,14 @@ class Hash | |||
| 		opts[:DocType] = self.class if Hash === opts | ||||
| 		YAML::quick_emit( self.object_id, opts ) { |out| | ||||
|             hash_type = to_yaml_type | ||||
|             if not out.options[:ExplicitTypes] and hash_type == "!map" | ||||
|             if not out.options(:ExplicitTypes) and hash_type == "!map" | ||||
|                 hash_type = "" | ||||
|             end | ||||
|             out.map( hash_type ) { |map| | ||||
| 				# | ||||
| 				# Sort the hash | ||||
| 				# | ||||
|                 if out.options[:SortKeys] | ||||
|                 if out.options(:SortKeys) | ||||
| 				    map.concat( self.sort ) | ||||
|                 else | ||||
|                     map.concat( self.to_a ) | ||||
|  | @ -213,7 +213,7 @@ class Array | |||
| 		opts[:DocType] = self.class if Hash === opts | ||||
| 		YAML::quick_emit( self.object_id, opts ) { |out| | ||||
|             array_type = to_yaml_type  | ||||
|             if not out.options[:ExplicitTypes] and array_type == "!seq" | ||||
|             if not out.options(:ExplicitTypes) and array_type == "!seq" | ||||
|                 array_type = "" | ||||
|             end | ||||
| 			 | ||||
|  | @ -302,7 +302,7 @@ class String | |||
|                 end | ||||
|             end | ||||
|             if not complex | ||||
|                 ostr = 	if out.options[:KeepValue] | ||||
|                 ostr = 	if out.options(:KeepValue) | ||||
|                             self | ||||
|                         elsif empty? | ||||
|                             "''" | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ module YAML | |||
|             opts = @options.dup | ||||
| 			opts[:UseHeader] = true if @documents.length > 1 | ||||
| 			ct = 0 | ||||
|             out = Emitter.new( opts ) | ||||
|             out = YAML::Syck::Emitter.new( opts ) | ||||
|             @documents.each { |v| | ||||
|                 if ct > 0 | ||||
|                     out << "\n--- "  | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| # | ||||
| require 'syck' | ||||
| require 'yaml/basenode' | ||||
| require 'yaml/baseemitter' | ||||
| 
 | ||||
| module YAML | ||||
|     module Syck | ||||
|  | @ -15,5 +16,12 @@ module YAML | |||
|             include YAML::BaseNode | ||||
|         end | ||||
| 
 | ||||
|         # | ||||
|         # Mixin BaseEmitter functionality | ||||
|         # | ||||
|         class Emitter | ||||
|             include YAML::BaseEmitter | ||||
|         end | ||||
| 
 | ||||
|     end | ||||
| end | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 why
						why