@@ -245,6 +245,51 @@ mrb_str_chr(mrb_state *mrb, mrb_value self)
245245 return mrb_str_substr (mrb , self , 0 , 1 );
246246}
247247
248+ static mrb_value
249+ mrb_fixnum_chr (mrb_state * mrb , mrb_value num )
250+ {
251+ mrb_int cp = mrb_fixnum (num );
252+ #ifdef MRB_UTF8_STRING
253+ char utf8 [4 ];
254+ mrb_int len ;
255+
256+ if (cp < 0 || 0x10FFFF < cp ) {
257+ mrb_raisef (mrb , E_RANGE_ERROR , "%S out of char range" , num );
258+ }
259+ if (cp < 0x80 ) {
260+ utf8 [0 ] = (char )cp ;
261+ len = 1 ;
262+ }
263+ else if (cp < 0x800 ) {
264+ utf8 [0 ] = (char )(0xC0 | (cp >> 6 ));
265+ utf8 [1 ] = (char )(0x80 | (cp & 0x3F ));
266+ len = 2 ;
267+ }
268+ else if (cp < 0x10000 ) {
269+ utf8 [0 ] = (char )(0xE0 | (cp >> 12 ));
270+ utf8 [1 ] = (char )(0x80 | ((cp >> 6 ) & 0x3F ));
271+ utf8 [2 ] = (char )(0x80 | ( cp & 0x3F ));
272+ len = 3 ;
273+ }
274+ else {
275+ utf8 [0 ] = (char )(0xF0 | (cp >> 18 ));
276+ utf8 [1 ] = (char )(0x80 | ((cp >> 12 ) & 0x3F ));
277+ utf8 [2 ] = (char )(0x80 | ((cp >> 6 ) & 0x3F ));
278+ utf8 [3 ] = (char )(0x80 | ( cp & 0x3F ));
279+ len = 4 ;
280+ }
281+ return mrb_str_new (mrb , utf8 , len );
282+ #else
283+ char c ;
284+
285+ if (cp < 0 || 0xff < cp ) {
286+ mrb_raisef (mrb , E_RANGE_ERROR , "%S out of char range" , num );
287+ }
288+ c = (char )cp ;
289+ return mrb_str_new (mrb , & c , 1 );
290+ #endif
291+ }
292+
248293/*
249294 * call-seq:
250295 * string.lines -> array of string
@@ -422,6 +467,72 @@ mrb_str_prepend(mrb_state *mrb, mrb_value self)
422467 return self ;
423468}
424469
470+ #ifdef MRB_UTF8_STRING
471+ static const char utf8len_codepage_zero [256 ] =
472+ {
473+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
474+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
475+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
476+ 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,
477+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
478+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
479+ 2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,
480+ 3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,4 ,4 ,4 ,4 ,4 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
481+ };
482+
483+ static mrb_int
484+ utf8code (unsigned char * p )
485+ {
486+ mrb_int len ;
487+
488+ if (p [0 ] < 0x80 )
489+ return p [0 ];
490+
491+ len = utf8len_codepage_zero [p [0 ]];
492+ if (len > 1 && (p [1 ] & 0xc0 ) == 0x80 ) {
493+ if (len == 2 )
494+ return ((p [0 ] & 0x1f ) << 6 ) + (p [1 ] & 0x3f );
495+ if ((p [2 ] & 0xc0 ) == 0x80 ) {
496+ if (len == 3 )
497+ return ((p [0 ] & 0x0f ) << 12 ) + ((p [1 ] & 0x3f ) << 6 )
498+ + (p [2 ] & 0x3f );
499+ if ((p [3 ] & 0xc0 ) == 0x80 ) {
500+ if (len == 4 )
501+ return ((p [0 ] & 0x07 ) << 18 ) + ((p [1 ] & 0x3f ) << 12 )
502+ + ((p [2 ] & 0x3f ) << 6 ) + (p [3 ] & 0x3f );
503+ if ((p [4 ] & 0xc0 ) == 0x80 ) {
504+ if (len == 5 )
505+ return ((p [0 ] & 0x03 ) << 24 ) + ((p [1 ] & 0x3f ) << 18 )
506+ + ((p [2 ] & 0x3f ) << 12 ) + ((p [3 ] & 0x3f ) << 6 )
507+ + (p [4 ] & 0x3f );
508+ if ((p [5 ] & 0xc0 ) == 0x80 && len == 6 )
509+ return ((p [0 ] & 0x01 ) << 30 ) + ((p [1 ] & 0x3f ) << 24 )
510+ + ((p [2 ] & 0x3f ) << 18 ) + ((p [3 ] & 0x3f ) << 12 )
511+ + ((p [4 ] & 0x3f ) << 6 ) + (p [5 ] & 0x3f );
512+ }
513+ }
514+ }
515+ }
516+ return p [0 ];
517+ }
518+
519+ static mrb_value
520+ mrb_str_ord (mrb_state * mrb , mrb_value str )
521+ {
522+ if (RSTRING_LEN (str ) == 0 )
523+ mrb_raise (mrb , E_ARGUMENT_ERROR , "empty string" );
524+ return mrb_fixnum_value (utf8code ((unsigned char * ) RSTRING_PTR (str )));
525+ }
526+ #else
527+ static mrb_value
528+ mrb_str_ord (mrb_state * mrb , mrb_value str )
529+ {
530+ if (RSTRING_LEN (str ) == 0 )
531+ mrb_raise (mrb , E_ARGUMENT_ERROR , "empty string" );
532+ return mrb_fixnum_value (RSTRING_PTR (str )[0 ]);
533+ }
534+ #endif
535+
425536void
426537mrb_mruby_string_ext_gem_init (mrb_state * mrb )
427538{
@@ -446,6 +557,9 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
446557 mrb_define_method (mrb , s , "prepend" , mrb_str_prepend , MRB_ARGS_REQ (1 ));
447558 mrb_alias_method (mrb , s , mrb_intern_lit (mrb , "next" ), mrb_intern_lit (mrb , "succ" ));
448559 mrb_alias_method (mrb , s , mrb_intern_lit (mrb , "next!" ), mrb_intern_lit (mrb , "succ!" ));
560+ mrb_define_method (mrb , s , "ord" , mrb_str_ord , MRB_ARGS_NONE ());
561+
562+ mrb_define_method (mrb , mrb -> fixnum_class , "chr" , mrb_fixnum_chr , MRB_ARGS_NONE ());
449563}
450564
451565void
0 commit comments