mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
string.c
00001 #include <ctype.h> 00002 #include <string.h> 00003 #include "mruby.h" 00004 #include "mruby/array.h" 00005 #include "mruby/class.h" 00006 #include "mruby/string.h" 00007 00008 static mrb_value 00009 mrb_str_getbyte(mrb_state *mrb, mrb_value str) 00010 { 00011 mrb_int pos; 00012 mrb_get_args(mrb, "i", &pos); 00013 00014 if (pos < 0) 00015 pos += RSTRING_LEN(str); 00016 if (pos < 0 || RSTRING_LEN(str) <= pos) 00017 return mrb_nil_value(); 00018 00019 return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]); 00020 } 00021 00022 /* 00023 * call-seq: 00024 * str.swapcase! -> str or nil 00025 * 00026 * Equivalent to <code>String#swapcase</code>, but modifies the receiver in 00027 * place, returning <i>str</i>, or <code>nil</code> if no changes were made. 00028 * Note: case conversion is effective only in ASCII region. 00029 */ 00030 static mrb_value 00031 mrb_str_swapcase_bang(mrb_state *mrb, mrb_value str) 00032 { 00033 char *p, *pend; 00034 int modify = 0; 00035 struct RString *s = mrb_str_ptr(str); 00036 00037 mrb_str_modify(mrb, s); 00038 p = RSTRING_PTR(str); 00039 pend = p + RSTRING_LEN(str); 00040 while (p < pend) { 00041 if (ISUPPER(*p)) { 00042 *p = TOLOWER(*p); 00043 modify = 1; 00044 } 00045 else if (ISLOWER(*p)) { 00046 *p = TOUPPER(*p); 00047 modify = 1; 00048 } 00049 p++; 00050 } 00051 00052 if (modify) return str; 00053 return mrb_nil_value(); 00054 } 00055 00056 /* 00057 * call-seq: 00058 * str.swapcase -> new_str 00059 * 00060 * Returns a copy of <i>str</i> with uppercase alphabetic characters converted 00061 * to lowercase and lowercase characters converted to uppercase. 00062 * Note: case conversion is effective only in ASCII region. 00063 * 00064 * "Hello".swapcase #=> "hELLO" 00065 * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" 00066 */ 00067 static mrb_value 00068 mrb_str_swapcase(mrb_state *mrb, mrb_value self) 00069 { 00070 mrb_value str; 00071 00072 str = mrb_str_dup(mrb, self); 00073 mrb_str_swapcase_bang(mrb, str); 00074 return str; 00075 } 00076 00077 /* 00078 * call-seq: 00079 * str << integer -> str 00080 * str.concat(integer) -> str 00081 * str << obj -> str 00082 * str.concat(obj) -> str 00083 * 00084 * Append---Concatenates the given object to <i>str</i>. If the object is a 00085 * <code>Integer</code>, it is considered as a codepoint, and is converted 00086 * to a character before concatenation. 00087 * 00088 * a = "hello " 00089 * a << "world" #=> "hello world" 00090 * a.concat(33) #=> "hello world!" 00091 */ 00092 static mrb_value 00093 mrb_str_concat2(mrb_state *mrb, mrb_value self) 00094 { 00095 mrb_value str; 00096 mrb_get_args(mrb, "S", &str); 00097 mrb_str_concat(mrb, self, str); 00098 return self; 00099 } 00100 00101 /* 00102 * call-seq: 00103 * str.start_with?([prefixes]+) -> true or false 00104 * 00105 * Returns true if +str+ starts with one of the +prefixes+ given. 00106 * 00107 * "hello".start_with?("hell") #=> true 00108 * 00109 * # returns true if one of the prefixes matches. 00110 * "hello".start_with?("heaven", "hell") #=> true 00111 * "hello".start_with?("heaven", "paradise") #=> false 00112 * "h".start_with?("heaven", "hell") #=> false 00113 */ 00114 static mrb_value 00115 mrb_str_start_with(mrb_state *mrb, mrb_value self) 00116 { 00117 mrb_value *argv, sub; 00118 mrb_int argc, i; 00119 mrb_get_args(mrb, "*", &argv, &argc); 00120 00121 for (i = 0; i < argc; i++) { 00122 size_t len_l, len_r; 00123 int ai = mrb_gc_arena_save(mrb); 00124 sub = mrb_string_type(mrb, argv[i]); 00125 mrb_gc_arena_restore(mrb, ai); 00126 len_l = RSTRING_LEN(self); 00127 len_r = RSTRING_LEN(sub); 00128 if (len_l >= len_r) { 00129 if (memcmp(RSTRING_PTR(self), RSTRING_PTR(sub), len_r) == 0) { 00130 return mrb_true_value(); 00131 } 00132 } 00133 } 00134 return mrb_false_value(); 00135 } 00136 00137 /* 00138 * call-seq: 00139 * str.end_with?([suffixes]+) -> true or false 00140 * 00141 * Returns true if +str+ ends with one of the +suffixes+ given. 00142 */ 00143 static mrb_value 00144 mrb_str_end_with(mrb_state *mrb, mrb_value self) 00145 { 00146 mrb_value *argv, sub; 00147 mrb_int argc, i; 00148 mrb_get_args(mrb, "*", &argv, &argc); 00149 00150 for (i = 0; i < argc; i++) { 00151 size_t len_l, len_r; 00152 int ai = mrb_gc_arena_save(mrb); 00153 sub = mrb_string_type(mrb, argv[i]); 00154 mrb_gc_arena_restore(mrb, ai); 00155 len_l = RSTRING_LEN(self); 00156 len_r = RSTRING_LEN(sub); 00157 if (len_l >= len_r) { 00158 if (memcmp(RSTRING_PTR(self) + (len_l - len_r), 00159 RSTRING_PTR(sub), 00160 len_r) == 0) { 00161 return mrb_true_value(); 00162 } 00163 } 00164 } 00165 return mrb_false_value(); 00166 } 00167 00168 static mrb_value 00169 mrb_str_hex(mrb_state *mrb, mrb_value self) 00170 { 00171 return mrb_str_to_inum(mrb, self, 16, FALSE); 00172 } 00173 00174 static mrb_value 00175 mrb_str_oct(mrb_state *mrb, mrb_value self) 00176 { 00177 return mrb_str_to_inum(mrb, self, 8, FALSE); 00178 } 00179 00180 /* 00181 * call-seq: 00182 * string.chr -> string 00183 * 00184 * Returns a one-character string at the beginning of the string. 00185 * 00186 * a = "abcde" 00187 * a.chr #=> "a" 00188 */ 00189 static mrb_value 00190 mrb_str_chr(mrb_state *mrb, mrb_value self) 00191 { 00192 return mrb_str_substr(mrb, self, 0, 1); 00193 } 00194 00195 /* 00196 * call-seq: 00197 * string.lines -> array of string 00198 * 00199 * Returns strings per line; 00200 * 00201 * a = "abc\ndef" 00202 * a.lines #=> ["abc\n", "def"] 00203 */ 00204 static mrb_value 00205 mrb_str_lines(mrb_state *mrb, mrb_value self) 00206 { 00207 mrb_value result; 00208 mrb_value blk; 00209 int ai; 00210 mrb_int len; 00211 mrb_value arg; 00212 char *p = RSTRING_PTR(self), *t; 00213 char *e = p + RSTRING_LEN(self); 00214 00215 mrb_get_args(mrb, "&", &blk); 00216 00217 result = mrb_ary_new(mrb); 00218 00219 if (!mrb_nil_p(blk)) { 00220 while (p < e) { 00221 t = p; 00222 while (p < e && *p != '\n') p++; 00223 if (*p == '\n') p++; 00224 len = (mrb_int) (p - t); 00225 arg = mrb_str_new(mrb, t, len); 00226 mrb_yield_argv(mrb, blk, 1, &arg); 00227 } 00228 return self; 00229 } 00230 while (p < e) { 00231 ai = mrb_gc_arena_save(mrb); 00232 t = p; 00233 while (p < e && *p != '\n') p++; 00234 if (*p == '\n') p++; 00235 len = (mrb_int) (p - t); 00236 mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len)); 00237 mrb_gc_arena_restore(mrb, ai); 00238 } 00239 return result; 00240 } 00241 00242 /* 00243 * call-seq: 00244 * string.succ -> string 00245 * 00246 * Returns next sequence of the string; 00247 * 00248 * a = "abc" 00249 * a.succ #=> "abd" 00250 */ 00251 static mrb_value 00252 mrb_str_succ_bang(mrb_state *mrb, mrb_value self) 00253 { 00254 mrb_value result; 00255 unsigned char *p, *e, *b, *t; 00256 char *prepend; 00257 struct RString *s = mrb_str_ptr(self); 00258 size_t l; 00259 00260 if (RSTRING_LEN(self) == 0) 00261 return self; 00262 00263 mrb_str_modify(mrb, s); 00264 l = RSTRING_LEN(self); 00265 b = p = (unsigned char*) RSTRING_PTR(self); 00266 t = e = p + l; 00267 *(e--) = 0; 00268 00269 // find trailing ascii/number 00270 while (e >= b) { 00271 if (ISALNUM(*e)) 00272 break; 00273 e--; 00274 } 00275 if (e < b) { 00276 e = p + l - 1; 00277 result = mrb_str_new_lit(mrb, ""); 00278 } else { 00279 // find leading letter of the ascii/number 00280 b = e; 00281 while (b > p) { 00282 if (!ISALNUM(*b) || (ISALNUM(*b) && *b != '9' && *b != 'z' && *b != 'Z')) 00283 break; 00284 b--; 00285 } 00286 if (!ISALNUM(*b)) 00287 b++; 00288 result = mrb_str_new(mrb, (char*) p, b - p); 00289 } 00290 00291 while (e >= b) { 00292 if (!ISALNUM(*e)) { 00293 if (*e == 0xff) { 00294 mrb_str_cat_lit(mrb, result, "\x01"); 00295 (*e) = 0; 00296 } else 00297 (*e)++; 00298 break; 00299 } 00300 prepend = NULL; 00301 if (*e == '9') { 00302 if (e == b) prepend = "1"; 00303 *e = '0'; 00304 } else if (*e == 'z') { 00305 if (e == b) prepend = "a"; 00306 *e = 'a'; 00307 } else if (*e == 'Z') { 00308 if (e == b) prepend = "A"; 00309 *e = 'A'; 00310 } else { 00311 (*e)++; 00312 break; 00313 } 00314 if (prepend) mrb_str_cat_cstr(mrb, result, prepend); 00315 e--; 00316 } 00317 result = mrb_str_cat(mrb, result, (char*) b, t - b); 00318 l = RSTRING_LEN(result); 00319 mrb_str_resize(mrb, self, l); 00320 memcpy(RSTRING_PTR(self), RSTRING_PTR(result), l); 00321 return self; 00322 } 00323 00324 static mrb_value 00325 mrb_str_succ(mrb_state *mrb, mrb_value self) 00326 { 00327 mrb_value str; 00328 00329 str = mrb_str_dup(mrb, self); 00330 mrb_str_succ_bang(mrb, str); 00331 return str; 00332 } 00333 00334 void 00335 mrb_mruby_string_ext_gem_init(mrb_state* mrb) 00336 { 00337 struct RClass * s = mrb->string_class; 00338 00339 mrb_define_method(mrb, s, "dump", mrb_str_dump, MRB_ARGS_NONE()); 00340 mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1)); 00341 mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, MRB_ARGS_NONE()); 00342 mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, MRB_ARGS_NONE()); 00343 mrb_define_method(mrb, s, "concat", mrb_str_concat2, MRB_ARGS_REQ(1)); 00344 mrb_define_method(mrb, s, "<<", mrb_str_concat2, MRB_ARGS_REQ(1)); 00345 mrb_define_method(mrb, s, "start_with?", mrb_str_start_with, MRB_ARGS_REST()); 00346 mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, MRB_ARGS_REST()); 00347 mrb_define_method(mrb, s, "hex", mrb_str_hex, MRB_ARGS_NONE()); 00348 mrb_define_method(mrb, s, "oct", mrb_str_oct, MRB_ARGS_NONE()); 00349 mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE()); 00350 mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE()); 00351 mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); 00352 mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); 00353 mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); 00354 mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); 00355 } 00356 00357 void 00358 mrb_mruby_string_ext_gem_final(mrb_state* mrb) 00359 { 00360 } 00361
Generated on Tue Jul 12 2022 18:00:35 by 1.7.2