edn_turbo 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +2 -0
 - data/Gemfile +2 -0
 - data/Rakefile +2 -3
 - data/bin/ppedn +11 -12
 - data/bin/ppedn-ruby +6 -5
 - data/ext/edn_turbo/depend +5 -3
 - data/ext/edn_turbo/edn_parser.cc +297 -295
 - data/ext/edn_turbo/edn_parser.rl +20 -18
 - data/ext/edn_turbo/extconf.rb +7 -11
 - data/ext/edn_turbo/main.cc +28 -27
 - data/ext/edn_turbo/{edn_parser.h → parser.h} +0 -42
 - data/ext/edn_turbo/parser_def.cc +197 -0
 - data/ext/edn_turbo/util.cc +240 -0
 - data/ext/edn_turbo/util.h +39 -0
 - data/ext/edn_turbo/util_unicode.cc +36 -0
 - data/ext/edn_turbo/util_unicode.h +14 -0
 - data/lib/edn_turbo/edn_parser.rb +6 -3
 - data/lib/edn_turbo/version.rb +4 -2
 - data/lib/edn_turbo.rb +2 -0
 - data/test/test_output_diff.rb +38 -49
 - metadata +9 -7
 - data/ext/edn_turbo/edn_parser_util.cc +0 -424
 - data/ext/edn_turbo/edn_parser_util.h +0 -11
 - data/ext/edn_turbo/edn_parser_util_unicode.cc +0 -33
 
    
        data/ext/edn_turbo/edn_parser.rl
    CHANGED
    
    | 
         @@ -1,12 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include <iostream>
         
     | 
| 
       2 
2 
     | 
    
         
             
            #include <string>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <sstream>
         
     | 
| 
       3 
4 
     | 
    
         
             
            #include <vector>
         
     | 
| 
       4 
5 
     | 
    
         
             
            #include <exception>
         
     | 
| 
       5 
6 
     | 
    
         
             
            #include <cstring>
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            #include <ruby/ruby.h>
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            #include " 
     | 
| 
      
 10 
     | 
    
         
            +
            #include "util.h"
         
     | 
| 
      
 11 
     | 
    
         
            +
            #include "parser.h"
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
            //
         
     | 
| 
       12 
14 
     | 
    
         
             
            // EDN spec at: https://github.com/edn-format/edn
         
     | 
| 
         @@ -120,7 +122,7 @@ 
     | 
|
| 
       120 
122 
     | 
    
         
             
                        else if (std::strcmp(RSTRING_PTR(sym), "false") == 0) { v = Qfalse; }
         
     | 
| 
       121 
123 
     | 
    
         
             
                        else if (std::strcmp(RSTRING_PTR(sym), "nil") == 0)   { v = Qnil; }
         
     | 
| 
       122 
124 
     | 
    
         
             
                        else {
         
     | 
| 
       123 
     | 
    
         
            -
                            v =  
     | 
| 
      
 125 
     | 
    
         
            +
                            v = edn::util::call_module_fn(rb_mEDN, EDN_MAKE_SYMBOL_METHOD, sym);
         
     | 
| 
       124 
126 
     | 
    
         
             
                        }
         
     | 
| 
       125 
127 
     | 
    
         
             
                        fexec np;
         
     | 
| 
       126 
128 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -207,7 +209,7 @@ const char *edn::Parser::parse_value(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       207 
209 
     | 
    
         
             
                write data;
         
     | 
| 
       208 
210 
     | 
    
         | 
| 
       209 
211 
     | 
    
         
             
                action parse_chars {
         
     | 
| 
       210 
     | 
    
         
            -
                    if ( 
     | 
| 
      
 212 
     | 
    
         
            +
                    if (edn::util::parse_byte_stream(p_save + 1, p, v, encode)) {
         
     | 
| 
       211 
213 
     | 
    
         
             
                        fexec p + 1;
         
     | 
| 
       212 
214 
     | 
    
         
             
                    } else {
         
     | 
| 
       213 
215 
     | 
    
         
             
                        fhold; fbreak;
         
     | 
| 
         @@ -322,7 +324,7 @@ const char* edn::Parser::parse_decimal(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       322 
324 
     | 
    
         
             
                %% write exec;
         
     | 
| 
       323 
325 
     | 
    
         | 
| 
       324 
326 
     | 
    
         
             
                if (cs >= EDN_decimal_first_final) {
         
     | 
| 
       325 
     | 
    
         
            -
                    v =  
     | 
| 
      
 327 
     | 
    
         
            +
                    v = edn::util::float_to_ruby(p_save, p - p_save);
         
     | 
| 
       326 
328 
     | 
    
         
             
                    return p + 1;
         
     | 
| 
       327 
329 
     | 
    
         
             
                }
         
     | 
| 
       328 
330 
     | 
    
         
             
                else if (cs == EDN_decimal_en_main) {} // silence ragel warning
         
     | 
| 
         @@ -354,7 +356,7 @@ const char* edn::Parser::parse_integer(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       354 
356 
     | 
    
         
             
                %% write exec;
         
     | 
| 
       355 
357 
     | 
    
         | 
| 
       356 
358 
     | 
    
         
             
                if (cs >= EDN_integer_first_final) {
         
     | 
| 
       357 
     | 
    
         
            -
                    v =  
     | 
| 
      
 359 
     | 
    
         
            +
                    v = edn::util::integer_to_ruby(p_save, p - p_save);
         
     | 
| 
       358 
360 
     | 
    
         
             
                    return p + 1;
         
     | 
| 
       359 
361 
     | 
    
         
             
                }
         
     | 
| 
       360 
362 
     | 
    
         
             
                else if (cs == EDN_integer_en_main) {} // silence ragel warning
         
     | 
| 
         @@ -382,7 +384,7 @@ const char* edn::Parser::parse_integer(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       382 
384 
     | 
    
         
             
                    const char *np = parse_symbol(p_save, pe, sym);
         
     | 
| 
       383 
385 
     | 
    
         
             
                    if (np == NULL) { fexec pe; } else {
         
     | 
| 
       384 
386 
     | 
    
         
             
                        if (sym != Qnil)
         
     | 
| 
       385 
     | 
    
         
            -
                            v =  
     | 
| 
      
 387 
     | 
    
         
            +
                            v = edn::util::call_module_fn(rb_mEDN, EDN_MAKE_SYMBOL_METHOD, sym);
         
     | 
| 
       386 
388 
     | 
    
         
             
                        fexec np;
         
     | 
| 
       387 
389 
     | 
    
         
             
                    }
         
     | 
| 
       388 
390 
     | 
    
         
             
                }
         
     | 
| 
         @@ -414,7 +416,7 @@ const char* edn::Parser::parse_integer(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       414 
416 
     | 
    
         
             
                    // stand-alone operators (-, +, /, ... etc)
         
     | 
| 
       415 
417 
     | 
    
         
             
                    char op[2] = { *p_save, 0 };
         
     | 
| 
       416 
418 
     | 
    
         
             
                    VALUE sym = rb_str_new2(op);
         
     | 
| 
       417 
     | 
    
         
            -
                    v =  
     | 
| 
      
 419 
     | 
    
         
            +
                    v = edn::util::call_module_fn(rb_mEDN, EDN_MAKE_SYMBOL_METHOD, sym);
         
     | 
| 
       418 
420 
     | 
    
         
             
                }
         
     | 
| 
       419 
421 
     | 
    
         | 
| 
       420 
422 
     | 
    
         
             
                valid_non_numeric_chars = alpha|operators|':'|'#';
         
     | 
| 
         @@ -479,7 +481,7 @@ const char* edn::Parser::parse_esc_char(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       479 
481 
     | 
    
         | 
| 
       480 
482 
     | 
    
         
             
                if (cs >= EDN_escaped_char_first_final) {
         
     | 
| 
       481 
483 
     | 
    
         
             
                    // convert the escaped value to a character
         
     | 
| 
       482 
     | 
    
         
            -
                    if (! 
     | 
| 
      
 484 
     | 
    
         
            +
                    if (!edn::util::parse_escaped_char(p_save + 1, p, v)) {
         
     | 
| 
       483 
485 
     | 
    
         
             
                        return pe;
         
     | 
| 
       484 
486 
     | 
    
         
             
                    }
         
     | 
| 
       485 
487 
     | 
    
         
             
                    return p;
         
     | 
| 
         @@ -601,7 +603,7 @@ const char* edn::Parser::parse_symbol(const char *p, const char *pe, VALUE& s) 
     | 
|
| 
       601 
603 
     | 
    
         
             
                                // parse_value() read an element we care
         
     | 
| 
       602 
604 
     | 
    
         
             
                                // about. Bind the metadata to it and add it to
         
     | 
| 
       603 
605 
     | 
    
         
             
                                // the sequence
         
     | 
| 
       604 
     | 
    
         
            -
                                e =  
     | 
| 
      
 606 
     | 
    
         
            +
                                e = edn::util::call_module_fn(rb_mEDNT, EDNT_EXTENDED_VALUE_METHOD, e, ruby_meta());
         
     | 
| 
       605 
607 
     | 
    
         
             
                                rb_ary_push(elems, e);
         
     | 
| 
       606 
608 
     | 
    
         
             
                            }
         
     | 
| 
       607 
609 
     | 
    
         
             
                        } else {
         
     | 
| 
         @@ -692,7 +694,7 @@ const char* edn::Parser::parse_list(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       692 
694 
     | 
    
         
             
                if (cs >= EDN_list_first_final) {
         
     | 
| 
       693 
695 
     | 
    
         
             
                    v = elems;
         
     | 
| 
       694 
696 
     | 
    
         
             
                    // TODO: replace with this but first figure out why array is not unrolled by EDN::list()
         
     | 
| 
       695 
     | 
    
         
            -
                    //        v =  
     | 
| 
      
 697 
     | 
    
         
            +
                    //        v = edn::util::call_module_fn(EDN_MAKE_LIST_METHOD, elems);
         
     | 
| 
       696 
698 
     | 
    
         
             
                    return p + 1;
         
     | 
| 
       697 
699 
     | 
    
         
             
                }
         
     | 
| 
       698 
700 
     | 
    
         
             
                else if (cs == EDN_list_error) {
         
     | 
| 
         @@ -853,7 +855,7 @@ const char* edn::Parser::parse_set(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       853 
855 
     | 
    
         | 
| 
       854 
856 
     | 
    
         
             
                if (cs >= EDN_set_first_final) {
         
     | 
| 
       855 
857 
     | 
    
         
             
                    // all elements collected; now convert to a set
         
     | 
| 
       856 
     | 
    
         
            -
                    v =  
     | 
| 
      
 858 
     | 
    
         
            +
                    v = edn::util::call_module_fn(rb_mEDN, EDN_MAKE_SET_METHOD, elems);
         
     | 
| 
       857 
859 
     | 
    
         
             
                    return p + 1;
         
     | 
| 
       858 
860 
     | 
    
         
             
                }
         
     | 
| 
       859 
861 
     | 
    
         
             
                else if (cs == EDN_set_error) {
         
     | 
| 
         @@ -998,14 +1000,14 @@ const char* edn::Parser::parse_tagged(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       998 
1000 
     | 
    
         | 
| 
       999 
1001 
     | 
    
         
             
                    if (!sym_ok || !data_ok) {
         
     | 
| 
       1000 
1002 
     | 
    
         
             
                        error(__FUNCTION__, "tagged element symbol error", *p);
         
     | 
| 
       1001 
     | 
    
         
            -
                        v = 
     | 
| 
      
 1003 
     | 
    
         
            +
                        v = EDN_EOF_CONST;
         
     | 
| 
       1002 
1004 
     | 
    
         
             
                        return NULL;
         
     | 
| 
       1003 
1005 
     | 
    
         
             
                    }
         
     | 
| 
       1004 
1006 
     | 
    
         | 
| 
       1005 
1007 
     | 
    
         
             
                    try {
         
     | 
| 
       1006 
1008 
     | 
    
         
             
                        // tagged_element makes a call to ruby which may throw an
         
     | 
| 
       1007 
1009 
     | 
    
         
             
                        // exception when parsing the data
         
     | 
| 
       1008 
     | 
    
         
            -
                        v =  
     | 
| 
      
 1010 
     | 
    
         
            +
                        v = edn::util::call_module_fn(rb_mEDN, EDN_TAGGED_ELEM_METHOD, sym_name, data);
         
     | 
| 
       1009 
1011 
     | 
    
         
             
                        return p + 1;
         
     | 
| 
       1010 
1012 
     | 
    
         
             
                    } catch (std::exception& e) {
         
     | 
| 
       1011 
1013 
     | 
    
         
             
                        error(__FUNCTION__, e.what());
         
     | 
| 
         @@ -1016,7 +1018,7 @@ const char* edn::Parser::parse_tagged(const char *p, const char *pe, VALUE& v) 
     | 
|
| 
       1016 
1018 
     | 
    
         
             
                    error(__FUNCTION__, "tagged element symbol error", *p);
         
     | 
| 
       1017 
1019 
     | 
    
         
             
                }
         
     | 
| 
       1018 
1020 
     | 
    
         
             
                else if (cs == EDN_tagged_en_main) {} // silence ragel warning
         
     | 
| 
       1019 
     | 
    
         
            -
                v =   
     | 
| 
      
 1021 
     | 
    
         
            +
                v =  EDN_EOF_CONST;
         
     | 
| 
       1020 
1022 
     | 
    
         
             
                return NULL;
         
     | 
| 
       1021 
1023 
     | 
    
         
             
            }
         
     | 
| 
       1022 
1024 
     | 
    
         | 
| 
         @@ -1090,7 +1092,7 @@ const char* edn::Parser::parse_meta(const char *p, const char *pe) 
     | 
|
| 
       1090 
1092 
     | 
    
         
             
                        // metadata sequence to it
         
     | 
| 
       1091 
1093 
     | 
    
         
             
                        if (!meta_empty() && meta_size() == meta_sz) {
         
     | 
| 
       1092 
1094 
     | 
    
         
             
                            // this will empty the metadata sequence too
         
     | 
| 
       1093 
     | 
    
         
            -
                            result =  
     | 
| 
      
 1095 
     | 
    
         
            +
                            result = edn::util::call_module_fn(rb_mEDNT, EDNT_EXTENDED_VALUE_METHOD, result, ruby_meta());
         
     | 
| 
       1094 
1096 
     | 
    
         
             
                        }
         
     | 
| 
       1095 
1097 
     | 
    
         
             
                        fexec np;
         
     | 
| 
       1096 
1098 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -1107,7 +1109,7 @@ const char* edn::Parser::parse_meta(const char *p, const char *pe) 
     | 
|
| 
       1107 
1109 
     | 
    
         
             
            VALUE edn::Parser::parse(const char* src, std::size_t len)
         
     | 
| 
       1108 
1110 
     | 
    
         
             
            {
         
     | 
| 
       1109 
1111 
     | 
    
         
             
                int cs;
         
     | 
| 
       1110 
     | 
    
         
            -
                VALUE result =  
     | 
| 
      
 1112 
     | 
    
         
            +
                VALUE result = EDN_EOF_CONST;
         
     | 
| 
       1111 
1113 
     | 
    
         | 
| 
       1112 
1114 
     | 
    
         
             
                %% write init;
         
     | 
| 
       1113 
1115 
     | 
    
         
             
                set_source(src, len);
         
     | 
| 
         @@ -1115,7 +1117,7 @@ VALUE edn::Parser::parse(const char* src, std::size_t len) 
     | 
|
| 
       1115 
1117 
     | 
    
         | 
| 
       1116 
1118 
     | 
    
         
             
                if (cs == EDN_parser_error) {
         
     | 
| 
       1117 
1119 
     | 
    
         
             
                    error(__FUNCTION__, *p);
         
     | 
| 
       1118 
     | 
    
         
            -
                    return  
     | 
| 
      
 1120 
     | 
    
         
            +
                    return EDN_EOF_CONST;
         
     | 
| 
       1119 
1121 
     | 
    
         
             
                }
         
     | 
| 
       1120 
1122 
     | 
    
         
             
                else if (cs == EDN_parser_first_final) {
         
     | 
| 
       1121 
1123 
     | 
    
         
             
                    p = pe = eof = NULL;
         
     | 
| 
         @@ -1152,7 +1154,7 @@ VALUE edn::Parser::parse(const char* src, std::size_t len) 
     | 
|
| 
       1152 
1154 
     | 
    
         
             
                            else {
         
     | 
| 
       1153 
1155 
     | 
    
         
             
                                // a value was read and there's a pending metadata
         
     | 
| 
       1154 
1156 
     | 
    
         
             
                                // sequence. Bind them.
         
     | 
| 
       1155 
     | 
    
         
            -
                                value =  
     | 
| 
      
 1157 
     | 
    
         
            +
                                value = edn::util::call_module_fn(rb_mEDNT, EDNT_EXTENDED_VALUE_METHOD, value, ruby_meta());
         
     | 
| 
       1156 
1158 
     | 
    
         
             
                                state = TOKEN_OK;
         
     | 
| 
       1157 
1159 
     | 
    
         
             
                            }
         
     | 
| 
       1158 
1160 
     | 
    
         
             
                        } else if (!discard.empty()) {
         
     | 
    
        data/ext/edn_turbo/extconf.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'mkmf'
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            HEADER_DIRS = [
         
     | 
| 
         @@ -13,17 +15,11 @@ LIB_DIRS = [ 
     | 
|
| 
       13 
15 
     | 
    
         | 
| 
       14 
16 
     | 
    
         
             
            dir_config('edn_ext', HEADER_DIRS, LIB_DIRS)
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
            # feels very hackish to do this
         
     | 
| 
       17 
     | 
    
         
            -
            if RUBY_PLATFORM 
     | 
| 
       18 
     | 
    
         
            -
              $CXXFLAGS << ' -stdlib=libc++ -std=c++11'
         
     | 
| 
       19 
     | 
    
         
            -
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
            # feels very hackish to do this but the new icu4c needs it on MacOS
         
     | 
| 
      
 19 
     | 
    
         
            +
            $CXXFLAGS << ' -stdlib=libc++ -std=c++11' if RUBY_PLATFORM.match?(/darwin/)
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
            unless find_header('unicode/uversion.h')
         
     | 
| 
       22 
     | 
    
         
            -
              abort "icu4c headers missing"
         
     | 
| 
       23 
     | 
    
         
            -
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
            abort 'icu4c headers missing' unless find_header('unicode/uversion.h')
         
     | 
| 
       24 
22 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
            unless have_library('icuuc')
         
     | 
| 
       26 
     | 
    
         
            -
              abort "ic4c lib missing"
         
     | 
| 
       27 
     | 
    
         
            -
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
            abort 'ic4c lib missing' unless have_library('icuuc')
         
     | 
| 
       28 
24 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
            create_makefile( 
     | 
| 
      
 25 
     | 
    
         
            +
            create_makefile('edn_turbo/edn_turbo')
         
     | 
    
        data/ext/edn_turbo/main.cc
    CHANGED
    
    | 
         @@ -6,28 +6,27 @@ 
     | 
|
| 
       6 
6 
     | 
    
         
             
            #include <ruby/ruby.h>
         
     | 
| 
       7 
7 
     | 
    
         
             
            #include <ruby/io.h>
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
            #include " 
     | 
| 
      
 9 
     | 
    
         
            +
            #include "parser.h"
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            namespace edn {
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
      
 13 
     | 
    
         
            +
                VALUE rb_mEDN;
         
     | 
| 
       13 
14 
     | 
    
         
             
                VALUE rb_mEDNT;
         
     | 
| 
       14 
15 
     | 
    
         | 
| 
       15 
16 
     | 
    
         
             
                // Symbols used to call into the ruby world.
         
     | 
| 
       16 
     | 
    
         
            -
                VALUE  
     | 
| 
      
 17 
     | 
    
         
            +
                VALUE EDN_MAKE_SYMBOL_METHOD       = Qnil;
         
     | 
| 
      
 18 
     | 
    
         
            +
                VALUE EDN_MAKE_LIST_METHOD         = Qnil;
         
     | 
| 
      
 19 
     | 
    
         
            +
                VALUE EDN_MAKE_SET_METHOD          = Qnil;
         
     | 
| 
      
 20 
     | 
    
         
            +
                VALUE EDN_MAKE_BIG_DECIMAL_METHOD  = Qnil;
         
     | 
| 
      
 21 
     | 
    
         
            +
                VALUE EDN_TAGGED_ELEM_METHOD       = Qnil;
         
     | 
| 
      
 22 
     | 
    
         
            +
                VALUE EDNT_EXTENDED_VALUE_METHOD   = Qnil;
         
     | 
| 
       17 
23 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                VALUE  
     | 
| 
       19 
     | 
    
         
            -
                VALUE  
     | 
| 
       20 
     | 
    
         
            -
                VALUE  
     | 
| 
       21 
     | 
    
         
            -
                VALUE EDNT_MAKE_BIG_DECIMAL_METHOD  = Qnil;
         
     | 
| 
       22 
     | 
    
         
            -
                VALUE EDNT_TAGGED_ELEM_METHOD       = Qnil;
         
     | 
| 
       23 
     | 
    
         
            -
                VALUE EDNT_EXTENDED_VALUE_METHOD    = Qnil;
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                VALUE EDNT_STRING_TO_I_METHOD       = Qnil;
         
     | 
| 
       26 
     | 
    
         
            -
                VALUE EDNT_STRING_TO_F_METHOD       = Qnil;
         
     | 
| 
       27 
     | 
    
         
            -
                VALUE EDNT_READ_METHOD              = Qnil;
         
     | 
| 
      
 24 
     | 
    
         
            +
                VALUE RUBY_STRING_TO_I_METHOD      = Qnil;
         
     | 
| 
      
 25 
     | 
    
         
            +
                VALUE RUBY_STRING_TO_F_METHOD      = Qnil;
         
     | 
| 
      
 26 
     | 
    
         
            +
                VALUE RUBY_READ_METHOD             = Qnil;
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
28 
     | 
    
         
             
                // returned when EOF - defined as a constant in EDN module
         
     | 
| 
       30 
     | 
    
         
            -
                VALUE  
     | 
| 
      
 29 
     | 
    
         
            +
                VALUE EDN_EOF_CONST                = Qnil;
         
     | 
| 
       31 
30 
     | 
    
         | 
| 
       32 
31 
     | 
    
         
             
                //
         
     | 
| 
       33 
32 
     | 
    
         
             
                // Wrappers to hook the class w/ the C-api.
         
     | 
| 
         @@ -108,7 +107,7 @@ namespace edn { 
     | 
|
| 
       108 
107 
     | 
    
         
             
                          // this is very inefficient as it'll require read()
         
     | 
| 
       109 
108 
     | 
    
         
             
                          // calls from the ruby side (involves a lot of data
         
     | 
| 
       110 
109 
     | 
    
         
             
                          // wrapping, etc)
         
     | 
| 
       111 
     | 
    
         
            -
                          if (rb_respond_to(data,  
     | 
| 
      
 110 
     | 
    
         
            +
                          if (rb_respond_to(data, RUBY_READ_METHOD)) {
         
     | 
| 
       112 
111 
     | 
    
         
             
                              p->set_source(data);
         
     | 
| 
       113 
112 
     | 
    
         
             
                              break;
         
     | 
| 
       114 
113 
     | 
    
         
             
                          }
         
     | 
| 
         @@ -174,6 +173,7 @@ void Init_edn_turbo(void) 
     | 
|
| 
       174 
173 
     | 
    
         
             
                    rb_raise(rb_eRuntimeError, "Extension init error calling setlocale() - It appears your system's locale is not configured correctly.\n");
         
     | 
| 
       175 
174 
     | 
    
         
             
                }
         
     | 
| 
       176 
175 
     | 
    
         | 
| 
      
 176 
     | 
    
         
            +
                edn::rb_mEDN  = rb_const_get(rb_cObject, rb_intern("EDN"));
         
     | 
| 
       177 
177 
     | 
    
         
             
                edn::rb_mEDNT = rb_define_module("EDNT");
         
     | 
| 
       178 
178 
     | 
    
         | 
| 
       179 
179 
     | 
    
         
             
                // bind the ruby Parser class to the C++ one
         
     | 
| 
         @@ -187,19 +187,20 @@ void Init_edn_turbo(void) 
     | 
|
| 
       187 
187 
     | 
    
         
             
                rb_define_method(rb_cParser, "read", (VALUE(*)(ANYARGS)) &edn::next, 0 );
         
     | 
| 
       188 
188 
     | 
    
         | 
| 
       189 
189 
     | 
    
         
             
                // bind ruby methods we'll call - these should be defined in edn_turbo.rb
         
     | 
| 
       190 
     | 
    
         
            -
                edn:: 
     | 
| 
       191 
     | 
    
         
            -
                edn:: 
     | 
| 
       192 
     | 
    
         
            -
                edn:: 
     | 
| 
       193 
     | 
    
         
            -
                edn:: 
     | 
| 
       194 
     | 
    
         
            -
                edn:: 
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
                 
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
                 
     | 
| 
       200 
     | 
    
         
            -
                edn:: 
     | 
| 
      
 190 
     | 
    
         
            +
                edn::EDN_MAKE_SYMBOL_METHOD        = rb_intern("symbol");
         
     | 
| 
      
 191 
     | 
    
         
            +
                edn::EDN_MAKE_LIST_METHOD          = rb_intern("list");
         
     | 
| 
      
 192 
     | 
    
         
            +
                edn::EDN_MAKE_SET_METHOD           = rb_intern("set");
         
     | 
| 
      
 193 
     | 
    
         
            +
                edn::EDN_MAKE_BIG_DECIMAL_METHOD   = rb_intern("big_decimal");
         
     | 
| 
      
 194 
     | 
    
         
            +
                edn::EDN_TAGGED_ELEM_METHOD        = rb_intern("tagged_element");
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                // defined in EDNT - see edn_parser.rb
         
     | 
| 
      
 197 
     | 
    
         
            +
                edn::EDNT_EXTENDED_VALUE_METHOD     = rb_intern("extend_for_meta");
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                // ruby methods
         
     | 
| 
      
 200 
     | 
    
         
            +
                edn::RUBY_STRING_TO_I_METHOD       = rb_intern("to_i");
         
     | 
| 
      
 201 
     | 
    
         
            +
                edn::RUBY_STRING_TO_F_METHOD       = rb_intern("to_f");
         
     | 
| 
      
 202 
     | 
    
         
            +
                edn::RUBY_READ_METHOD              = rb_intern("read");
         
     | 
| 
       201 
203 
     | 
    
         | 
| 
       202 
204 
     | 
    
         
             
                // so we can return EOF directly
         
     | 
| 
       203 
     | 
    
         
            -
                 
     | 
| 
       204 
     | 
    
         
            -
                edn::EDNT_EOF_CONST                = rb_const_get(edn_module, rb_intern("EOF"));
         
     | 
| 
      
 205 
     | 
    
         
            +
                edn::EDN_EOF_CONST                 = rb_const_get(edn::rb_mEDN, rb_intern("EOF"));
         
     | 
| 
       205 
206 
     | 
    
         
             
            }
         
     | 
| 
         @@ -1,29 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #pragma once
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            #include <string>
         
     | 
| 
       4 
     | 
    
         
            -
            #include <sstream>
         
     | 
| 
       5 
4 
     | 
    
         
             
            #include <vector>
         
     | 
| 
       6 
5 
     | 
    
         
             
            #include <stack>
         
     | 
| 
       7 
6 
     | 
    
         | 
| 
       8 
7 
     | 
    
         | 
| 
       9 
8 
     | 
    
         
             
            namespace edn
         
     | 
| 
       10 
9 
     | 
    
         
             
            {
         
     | 
| 
       11 
     | 
    
         
            -
                extern VALUE rb_mEDNT;
         
     | 
| 
       12 
     | 
    
         
            -
                extern VALUE EDN_MODULE_SYMBOL;
         
     | 
| 
       13 
     | 
    
         
            -
                extern VALUE EDNT_MAKE_SYMBOL_METHOD;
         
     | 
| 
       14 
     | 
    
         
            -
                extern VALUE EDNT_MAKE_LIST_METHOD;
         
     | 
| 
       15 
     | 
    
         
            -
                extern VALUE EDNT_MAKE_SET_METHOD;
         
     | 
| 
       16 
     | 
    
         
            -
                extern VALUE EDNT_MAKE_BIG_DECIMAL_METHOD;
         
     | 
| 
       17 
     | 
    
         
            -
                extern VALUE EDNT_TAGGED_ELEM_METHOD;
         
     | 
| 
       18 
     | 
    
         
            -
                extern VALUE EDNT_EXTENDED_VALUE_METHOD;
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                extern VALUE EDNT_STRING_TO_I_METHOD;
         
     | 
| 
       21 
     | 
    
         
            -
                extern VALUE EDNT_STRING_TO_F_METHOD;
         
     | 
| 
       22 
     | 
    
         
            -
                extern VALUE EDNT_READ_METHOD;
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                extern VALUE EDNT_EOF_CONST;
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
10 
     | 
    
         
             
                //
         
     | 
| 
       28 
11 
     | 
    
         
             
                // C-extension EDN Parser class representation
         
     | 
| 
       29 
12 
     | 
    
         
             
                class Parser
         
     | 
| 
         @@ -50,8 +33,6 @@ namespace edn 
     | 
|
| 
       50 
33 
     | 
    
         
             
                    // returns the next element in the current stream
         
     | 
| 
       51 
34 
     | 
    
         
             
                    VALUE next();
         
     | 
| 
       52 
35 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                    static void throw_error(int error);
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
36 
     | 
    
         
             
                private:
         
     | 
| 
       56 
37 
     | 
    
         
             
                    // ragel needs these
         
     | 
| 
       57 
38 
     | 
    
         
             
                    const char* p;
         
     | 
| 
         @@ -89,18 +70,6 @@ namespace edn 
     | 
|
| 
       89 
70 
     | 
    
         | 
| 
       90 
71 
     | 
    
         
             
                    eTokenState parse_next(VALUE& value);
         
     | 
| 
       91 
72 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
                    // defined in edn_parser_util.cc
         
     | 
| 
       93 
     | 
    
         
            -
                    static VALUE integer_to_ruby(const char* str, std::size_t len);
         
     | 
| 
       94 
     | 
    
         
            -
                    static VALUE float_to_ruby  (const char* str, std::size_t len);
         
     | 
| 
       95 
     | 
    
         
            -
                    static VALUE ruby_io_read(VALUE io);
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
                    static bool parse_byte_stream (const char *p, const char *pe, VALUE& rslt, bool encode);
         
     | 
| 
       98 
     | 
    
         
            -
                    static bool parse_escaped_char(const char *p, const char *pe, VALUE& rslt);
         
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
                    static VALUE make_edn_type(ID method, VALUE value);
         
     | 
| 
       101 
     | 
    
         
            -
                    static VALUE make_edn_type(ID method, VALUE value1, VALUE value2);
         
     | 
| 
       102 
     | 
    
         
            -
                    static VALUE make_edn_type(VALUE module, ID method, VALUE value1, VALUE value2);
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
73 
     | 
    
         
             
                    // metadata
         
     | 
| 
       105 
74 
     | 
    
         
             
                    VALUE ruby_meta();
         
     | 
| 
       106 
75 
     | 
    
         
             
                    void  new_meta_list() { metadata.push( new std::vector<VALUE>() ); }
         
     | 
| 
         @@ -109,17 +78,6 @@ namespace edn 
     | 
|
| 
       109 
78 
     | 
    
         
             
                    bool  meta_empty() const { return metadata.top()->empty(); }
         
     | 
| 
       110 
79 
     | 
    
         
             
                    std::size_t meta_size() const { return metadata.top()->size(); }
         
     | 
| 
       111 
80 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                    // utility method to convert a primitive in string form to a
         
     | 
| 
       113 
     | 
    
         
            -
                    // ruby type
         
     | 
| 
       114 
     | 
    
         
            -
                    template <class T>
         
     | 
| 
       115 
     | 
    
         
            -
                    static inline T buftotype(const char* p, std::size_t len) {
         
     | 
| 
       116 
     | 
    
         
            -
                        T val;
         
     | 
| 
       117 
     | 
    
         
            -
                        std::string buf;
         
     | 
| 
       118 
     | 
    
         
            -
                        buf.append(p, len);
         
     | 
| 
       119 
     | 
    
         
            -
                        std::istringstream(buf) >> val;
         
     | 
| 
       120 
     | 
    
         
            -
                        return val;
         
     | 
| 
       121 
     | 
    
         
            -
                    }
         
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
81 
     | 
    
         
             
                    void error(const std::string& f, const std::string& err, char c) const;
         
     | 
| 
       124 
82 
     | 
    
         
             
                    void error(const std::string& f, char err_c) const { error(f, "", err_c); }
         
     | 
| 
       125 
83 
     | 
    
         
             
                    void error(const std::string& f, const std::string& err_msg) const { error(f, err_msg, '\0'); }
         
     | 
| 
         @@ -0,0 +1,197 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include <iostream>
         
     | 
| 
      
 2 
     | 
    
         
            +
            #include <string>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <stack>
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            #include <ruby/ruby.h>
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            #include "parser.h"
         
     | 
| 
      
 8 
     | 
    
         
            +
            #include "util.h"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            namespace edn
         
     | 
| 
      
 11 
     | 
    
         
            +
            {
         
     | 
| 
      
 12 
     | 
    
         
            +
                //
         
     | 
| 
      
 13 
     | 
    
         
            +
                // parser destructor
         
     | 
| 
      
 14 
     | 
    
         
            +
                Parser::~Parser()
         
     | 
| 
      
 15 
     | 
    
         
            +
                {
         
     | 
| 
      
 16 
     | 
    
         
            +
                    reset_state();
         
     | 
| 
      
 17 
     | 
    
         
            +
                    del_top_meta_list();
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    if (io_buffer) {
         
     | 
| 
      
 20 
     | 
    
         
            +
                        free(reinterpret_cast<void*>(io_buffer));
         
     | 
| 
      
 21 
     | 
    
         
            +
                    }
         
     | 
| 
      
 22 
     | 
    
         
            +
                }
         
     | 
| 
      
 23 
     | 
    
         
            +
                
         
     | 
| 
      
 24 
     | 
    
         
            +
                // =================================================================
         
     | 
| 
      
 25 
     | 
    
         
            +
                // for token-by-token parsing. If a discard or metadata is parsed,
         
     | 
| 
      
 26 
     | 
    
         
            +
                // attempt to get the following value
         
     | 
| 
      
 27 
     | 
    
         
            +
                //
         
     | 
| 
      
 28 
     | 
    
         
            +
                VALUE Parser::next()
         
     | 
| 
      
 29 
     | 
    
         
            +
                {
         
     | 
| 
      
 30 
     | 
    
         
            +
                    VALUE token = EDN_EOF_CONST;
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    // buffer if reading from an IO
         
     | 
| 
      
 33 
     | 
    
         
            +
                    if (core_io || (read_io != Qnil)) {
         
     | 
| 
      
 34 
     | 
    
         
            +
                        fill_buf();
         
     | 
| 
      
 35 
     | 
    
         
            +
                    }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    while (!is_eof())
         
     | 
| 
      
 38 
     | 
    
         
            +
                    {
         
     | 
| 
      
 39 
     | 
    
         
            +
                        // fetch a token. If it's metadata or discard
         
     | 
| 
      
 40 
     | 
    
         
            +
                        VALUE v = EDN_EOF_CONST;
         
     | 
| 
      
 41 
     | 
    
         
            +
                        eTokenState state = parse_next(v);
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                        if (state == TOKEN_OK) {
         
     | 
| 
      
 44 
     | 
    
         
            +
                            // valid token
         
     | 
| 
      
 45 
     | 
    
         
            +
                            token = v;
         
     | 
| 
      
 46 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 47 
     | 
    
         
            +
                        }
         
     | 
| 
      
 48 
     | 
    
         
            +
                        else if (state == TOKEN_ERROR) {
         
     | 
| 
      
 49 
     | 
    
         
            +
                            token = EDN_EOF_CONST;
         
     | 
| 
      
 50 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 51 
     | 
    
         
            +
                        }
         
     | 
| 
      
 52 
     | 
    
         
            +
                    }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    return token;
         
     | 
| 
      
 55 
     | 
    
         
            +
                }
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                // reset parsing state
         
     | 
| 
      
 58 
     | 
    
         
            +
                //
         
     | 
| 
      
 59 
     | 
    
         
            +
                void Parser::reset_state()
         
     | 
| 
      
 60 
     | 
    
         
            +
                {
         
     | 
| 
      
 61 
     | 
    
         
            +
                    line_number = 1;
         
     | 
| 
      
 62 
     | 
    
         
            +
                    discard.clear();
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    // remove any remaining levels except for the first
         
     | 
| 
      
 65 
     | 
    
         
            +
                    while (metadata.size() > 1) {
         
     | 
| 
      
 66 
     | 
    
         
            +
                        del_top_meta_list();
         
     | 
| 
      
 67 
     | 
    
         
            +
                    }
         
     | 
| 
      
 68 
     | 
    
         
            +
                    // but clear any metadata on the first
         
     | 
| 
      
 69 
     | 
    
         
            +
                    metadata.top()->clear();
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    // clean up
         
     | 
| 
      
 72 
     | 
    
         
            +
                    core_io = NULL;
         
     | 
| 
      
 73 
     | 
    
         
            +
                    read_io = Qnil;
         
     | 
| 
      
 74 
     | 
    
         
            +
                    p = pe = eof = NULL;
         
     | 
| 
      
 75 
     | 
    
         
            +
                }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                //
         
     | 
| 
      
 78 
     | 
    
         
            +
                // set a new source
         
     | 
| 
      
 79 
     | 
    
         
            +
                void Parser::set_source(const char* src, std::size_t len)
         
     | 
| 
      
 80 
     | 
    
         
            +
                {
         
     | 
| 
      
 81 
     | 
    
         
            +
                    reset_state();
         
     | 
| 
      
 82 
     | 
    
         
            +
                    // set ragel state
         
     | 
| 
      
 83 
     | 
    
         
            +
                    p = src;
         
     | 
| 
      
 84 
     | 
    
         
            +
                    pe = src + len;
         
     | 
| 
      
 85 
     | 
    
         
            +
                    eof = pe;
         
     | 
| 
      
 86 
     | 
    
         
            +
                }
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                void Parser::set_source(FILE* fp)
         
     | 
| 
      
 89 
     | 
    
         
            +
                {
         
     | 
| 
      
 90 
     | 
    
         
            +
                    reset_state();
         
     | 
| 
      
 91 
     | 
    
         
            +
                    core_io = fp;
         
     | 
| 
      
 92 
     | 
    
         
            +
                }
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                void Parser::set_source(VALUE str_io)
         
     | 
| 
      
 95 
     | 
    
         
            +
                {
         
     | 
| 
      
 96 
     | 
    
         
            +
                    reset_state();
         
     | 
| 
      
 97 
     | 
    
         
            +
                    read_io = str_io;
         
     | 
| 
      
 98 
     | 
    
         
            +
                }
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                //
         
     | 
| 
      
 101 
     | 
    
         
            +
                // for IO sources, read and fill a buffer
         
     | 
| 
      
 102 
     | 
    
         
            +
                void Parser::fill_buf()
         
     | 
| 
      
 103 
     | 
    
         
            +
                {
         
     | 
| 
      
 104 
     | 
    
         
            +
                    std::string str_buf;
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    // read as much data available
         
     | 
| 
      
 107 
     | 
    
         
            +
                    if (core_io) {
         
     | 
| 
      
 108 
     | 
    
         
            +
                        // ruby core IO types
         
     | 
| 
      
 109 
     | 
    
         
            +
                        char c;
         
     | 
| 
      
 110 
     | 
    
         
            +
                        while (1)
         
     | 
| 
      
 111 
     | 
    
         
            +
                        {
         
     | 
| 
      
 112 
     | 
    
         
            +
                            c = fgetc(core_io);
         
     | 
| 
      
 113 
     | 
    
         
            +
                            if (c == EOF) {
         
     | 
| 
      
 114 
     | 
    
         
            +
                                break;
         
     | 
| 
      
 115 
     | 
    
         
            +
                            }
         
     | 
| 
      
 116 
     | 
    
         
            +
                            str_buf += c;
         
     | 
| 
      
 117 
     | 
    
         
            +
                        }
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                    } else if (read_io != Qnil) {
         
     | 
| 
      
 120 
     | 
    
         
            +
                        // StringIO, etc. Call read() from ruby side
         
     | 
| 
      
 121 
     | 
    
         
            +
                        VALUE v = edn::util::ruby_io_read(read_io);
         
     | 
| 
      
 122 
     | 
    
         
            +
                        if (TYPE(v) == T_STRING) {
         
     | 
| 
      
 123 
     | 
    
         
            +
                            str_buf.assign( StringValuePtr(v), RSTRING_LEN(v));
         
     | 
| 
      
 124 
     | 
    
         
            +
                        }
         
     | 
| 
      
 125 
     | 
    
         
            +
                    }
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                    // set the buffer to read from
         
     | 
| 
      
 128 
     | 
    
         
            +
                    if (str_buf.length() > 0) {
         
     | 
| 
      
 129 
     | 
    
         
            +
                        // first time when io_buffer is NULL, pe & p = 0
         
     | 
| 
      
 130 
     | 
    
         
            +
                        uintmax_t new_length = (pe - p) + str_buf.length();
         
     | 
| 
      
 131 
     | 
    
         
            +
                        if (new_length > (((uintmax_t) 1 << 32) - 1)) {
         
     | 
| 
      
 132 
     | 
    
         
            +
                            // icu -> 32-bit. TODO: handle
         
     | 
| 
      
 133 
     | 
    
         
            +
                            rb_raise(rb_eRuntimeError, "Unsupported string buffer length");
         
     | 
| 
      
 134 
     | 
    
         
            +
                        }
         
     | 
| 
      
 135 
     | 
    
         
            +
                        char* start = NULL;
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                        // allocate or extend storage needed
         
     | 
| 
      
 138 
     | 
    
         
            +
                        if (!io_buffer) {
         
     | 
| 
      
 139 
     | 
    
         
            +
                            io_buffer = reinterpret_cast<char*>(malloc(new_length));
         
     | 
| 
      
 140 
     | 
    
         
            +
                            start = io_buffer;
         
     | 
| 
      
 141 
     | 
    
         
            +
                        } else if (io_buffer_len < new_length) {
         
     | 
| 
      
 142 
     | 
    
         
            +
                            // resize the buffer
         
     | 
| 
      
 143 
     | 
    
         
            +
                            io_buffer = reinterpret_cast<char*>(realloc(reinterpret_cast<void*>(io_buffer), new_length));
         
     | 
| 
      
 144 
     | 
    
         
            +
                        }
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                        if (!start) {
         
     | 
| 
      
 147 
     | 
    
         
            +
                            // appending to the buffer but move the data not yet
         
     | 
| 
      
 148 
     | 
    
         
            +
                            // parsed first to the front
         
     | 
| 
      
 149 
     | 
    
         
            +
                            memmove(io_buffer, p, pe - p);
         
     | 
| 
      
 150 
     | 
    
         
            +
                            start = io_buffer + (pe - p);
         
     | 
| 
      
 151 
     | 
    
         
            +
                        }
         
     | 
| 
      
 152 
     | 
    
         
            +
                        
         
     | 
| 
      
 153 
     | 
    
         
            +
                        // and copy
         
     | 
| 
      
 154 
     | 
    
         
            +
                        memcpy(start, str_buf.c_str(), str_buf.length()); 
         
     | 
| 
      
 155 
     | 
    
         
            +
                        io_buffer_len = (uint32_t) new_length;
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                        // set ragel state
         
     | 
| 
      
 158 
     | 
    
         
            +
                        p = io_buffer;
         
     | 
| 
      
 159 
     | 
    
         
            +
                        pe = p + new_length;
         
     | 
| 
      
 160 
     | 
    
         
            +
                        eof = pe;
         
     | 
| 
      
 161 
     | 
    
         
            +
                    }
         
     | 
| 
      
 162 
     | 
    
         
            +
                }
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                // =================================================================
         
     | 
| 
      
 165 
     | 
    
         
            +
                // METADATA
         
     | 
| 
      
 166 
     | 
    
         
            +
                //
         
     | 
| 
      
 167 
     | 
    
         
            +
                // returns an array of metadata value(s) saved in reverse order
         
     | 
| 
      
 168 
     | 
    
         
            +
                // (right to left) - the ruby side will interpret this
         
     | 
| 
      
 169 
     | 
    
         
            +
                VALUE Parser::ruby_meta()
         
     | 
| 
      
 170 
     | 
    
         
            +
                {
         
     | 
| 
      
 171 
     | 
    
         
            +
                    VALUE m_ary = rb_ary_new();
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                    // pop from the back of the top-most list
         
     | 
| 
      
 174 
     | 
    
         
            +
                    while (!metadata.top()->empty()) {
         
     | 
| 
      
 175 
     | 
    
         
            +
                        rb_ary_push(m_ary, metadata.top()->back());
         
     | 
| 
      
 176 
     | 
    
         
            +
                        metadata.top()->pop_back();
         
     | 
| 
      
 177 
     | 
    
         
            +
                    }
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                    return m_ary;
         
     | 
| 
      
 180 
     | 
    
         
            +
                }
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                // =================================================================
         
     | 
| 
      
 184 
     | 
    
         
            +
                //
         
     | 
| 
      
 185 
     | 
    
         
            +
                // error reporting
         
     | 
| 
      
 186 
     | 
    
         
            +
                void Parser::error(const std::string& func, const std::string& err, char c) const
         
     | 
| 
      
 187 
     | 
    
         
            +
                {
         
     | 
| 
      
 188 
     | 
    
         
            +
                    std::cerr << "Parse error "
         
     | 
| 
      
 189 
     | 
    
         
            +
                        //            "from " << func << "() "
         
     | 
| 
      
 190 
     | 
    
         
            +
                        ;
         
     | 
| 
      
 191 
     | 
    
         
            +
                    if (err.length() > 0)
         
     | 
| 
      
 192 
     | 
    
         
            +
                        std::cerr << "(" << err << ") ";
         
     | 
| 
      
 193 
     | 
    
         
            +
                    if (c != '\0')
         
     | 
| 
      
 194 
     | 
    
         
            +
                        std::cerr << "at '" << c << "' ";
         
     | 
| 
      
 195 
     | 
    
         
            +
                    std::cerr << "on line " << line_number << std::endl;
         
     | 
| 
      
 196 
     | 
    
         
            +
                }
         
     | 
| 
      
 197 
     | 
    
         
            +
            }
         
     |