move range aware aget to array.c from mruby-array-ext gem
[mruby.git] / src / string.c
index 328266d..6e5f91e 100644 (file)
@@ -5,12 +5,7 @@
 */
 
 #include <ctype.h>
-#ifndef SIZE_MAX
- /* Some versions of VC++
-  * has SIZE_MAX in stdint.h
-  */
-# include <limits.h>
-#endif
+#include <limits.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,9 +25,6 @@ typedef struct mrb_shared_string {
   mrb_int len;
 } mrb_shared_string;
 
-#define MRB_STR_SHARED    1
-#define MRB_STR_NOFREE    2
-
 static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2);
 static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
 
@@ -62,6 +54,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
     if (shared->refcnt == 1 && s->ptr == shared->ptr) {
       s->ptr = shared->ptr;
       s->aux.capa = shared->len;
+      s->ptr[s->len] = '\0';
       mrb_free(mrb, shared);
     }
     else {
@@ -74,7 +67,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
       if (p) {
         memcpy(ptr, p, len);
       }
-      ptr[len] = 0;
+      ptr[len] =  '\0';
       s->ptr = ptr;
       s->aux.capa = len;
       str_decref(mrb, shared);
@@ -91,6 +84,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
     }
     s->ptr[s->len] = '\0';
     s->aux.capa = s->len;
+    s->flags &= ~MRB_STR_NOFREE;
     return;
   }
 }
@@ -113,16 +107,6 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
   return str;
 }
 
-static inline void
-str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len)
-{
-  struct RString *s = mrb_str_ptr(str);
-
-  if (s->ptr != p || s->len != len) {
-    mrb_raise(mrb, E_RUNTIME_ERROR, "string modified");
-  }
-}
-
 #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
 
 /* char offset to byte offset */
@@ -331,34 +315,6 @@ str_make_shared(mrb_state *mrb, struct RString *s)
 }
 
 /*
- *  call-seq: (Caution! string literal)
- *     String.new(str="")   => new_str
- *
- *  Returns a new string object containing a copy of <i>str</i>.
- */
-
-mrb_value
-mrb_str_literal(mrb_state *mrb, mrb_value str)
-{
-  struct RString *s, *orig;
-  mrb_shared_string *shared;
-
-  s = mrb_obj_alloc_string(mrb);
-  orig = mrb_str_ptr(str);
-  if (!(orig->flags & MRB_STR_SHARED)) {
-    str_make_shared(mrb, orig);
-  }
-  shared = orig->aux.shared;
-  shared->refcnt++;
-  s->ptr = shared->ptr;
-  s->len = shared->len;
-  s->aux.shared = shared;
-  s->flags |= MRB_STR_SHARED;
-
-  return mrb_obj_value(s);
-}
-
-/*
  *  call-seq:
  *     char* str = String("abcd"), len=strlen("abcd")
  *
@@ -398,7 +354,7 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
   }
   memcpy(s1->ptr+s1->len, s2->ptr, s2->len);
   s1->len = len;
-  s1->ptr[len] = 0;
+  s1->ptr[len] =  '\0';
 }
 
 /*
@@ -573,10 +529,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
 
   mrb_get_args(mrb, "o", &str2);
   if (!mrb_string_p(str2)) {
-    if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) {
+    if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_s"))) {
       return mrb_nil_value();
     }
-    else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) {
+    else if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "<=>"))) {
       return mrb_nil_value();
     }
     else {
@@ -595,7 +551,7 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
   return mrb_fixnum_value(result);
 }
 
-static int
+static mrb_bool
 str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
 {
   const mrb_int len = RSTRING_LEN(str1);
@@ -606,13 +562,13 @@ str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
   return FALSE;
 }
 
-int
+mrb_bool
 mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
 {
   if (mrb_obj_equal(mrb, str1, str2)) return TRUE;
   if (!mrb_string_p(str2)) {
     if (mrb_nil_p(str2)) return FALSE;
-    if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) {
+    if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) {
       return FALSE;
     }
     str2 = mrb_funcall(mrb, str2, "to_str", 0);
@@ -785,12 +741,10 @@ num_index:
       /* check if indx is Range */
       {
         mrb_int beg, len;
-        mrb_value tmp;
 
         len = RSTRING_LEN(str);
         if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) {
-          tmp = mrb_str_subseq(mrb, str, beg, len);
-          return tmp;
+          return mrb_str_subseq(mrb, str, beg, len);
         }
         else {
           return mrb_nil_value();
@@ -1277,7 +1231,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
   mrb_bool include_p;
 
   mrb_get_args(mrb, "o", &str2);
-  if (mrb_type(str2) == MRB_TT_FIXNUM) {
+  if (mrb_fixnum_p(str2)) {
     include_p = (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)) != NULL);
   }
   else {
@@ -1499,7 +1453,7 @@ mrb_ptr_to_str(mrb_state *mrb, void *p)
   struct RString *p_str;
   char *p1;
   char *p2;
-  intptr_t n = (intptr_t)p;
+  uintptr_t n = (uintptr_t)p;
 
   p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
   p1 = p_str->ptr;
@@ -1524,6 +1478,12 @@ mrb_ptr_to_str(mrb_state *mrb, void *p)
 }
 
 mrb_value
+mrb_string_type(mrb_state *mrb, mrb_value str)
+{
+  return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
+}
+
+mrb_value
 mrb_check_string_type(mrb_state *mrb, mrb_value str)
 {
   return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
@@ -2347,47 +2307,47 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
         *q++ = '\\';
         *q++ = 'n';
         break;
-    
+
       case '\r':
         *q++ = '\\';
         *q++ = 'r';
         break;
-    
+
       case '\t':
         *q++ = '\\';
         *q++ = 't';
         break;
-    
+
       case '\f':
         *q++ = '\\';
         *q++ = 'f';
         break;
-    
+
       case '\013':
         *q++ = '\\';
         *q++ = 'v';
         break;
-    
+
       case '\010':
         *q++ = '\\';
         *q++ = 'b';
         break;
-    
+
       case '\007':
         *q++ = '\\';
         *q++ = 'a';
         break;
-    
+
       case '\033':
         *q++ = '\\';
         *q++ = 'e';
         break;
-    
+
       case '#':
         if (IS_EVSTR(p, pend)) *q++ = '\\';
         *q++ = '#';
         break;
-  
+
       default:
         if (ISPRINT(c)) {
           *q++ = c;
@@ -2450,7 +2410,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
 
     p = RSTRING_PTR(str); pend = RSTRING_END(str);
     for (;p < pend; p++) {
-      unsigned int c, cc;
+      unsigned char c, cc;
 
       c = *p;
       if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
@@ -2527,14 +2487,13 @@ mrb_init_string(mrb_state *mrb)
   MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
   mrb_include_module(mrb, s, mrb_class_get(mrb, "Comparable"));
 
-  mrb_define_method(mrb, s, "+",               mrb_str_plus_m,          MRB_ARGS_REQ(1)); /* 15.2.10.5.2  */
+
   mrb_define_method(mrb, s, "bytesize",        mrb_str_bytesize,        MRB_ARGS_NONE());
-  mrb_define_method(mrb, s, "size",            mrb_str_size,            MRB_ARGS_NONE()); /* 15.2.10.5.33 */
-  mrb_define_method(mrb, s, "length",          mrb_str_size,            MRB_ARGS_NONE()); /* 15.2.10.5.26 */
-  mrb_define_method(mrb, s, "*",               mrb_str_times,           MRB_ARGS_REQ(1)); /* 15.2.10.5.1  */
-  mrb_define_method(mrb, s, "<=>",             mrb_str_cmp_m,           MRB_ARGS_REQ(1)); /* 15.2.10.5.3  */
-  mrb_define_method(mrb, s, "==",              mrb_str_equal_m,         MRB_ARGS_REQ(1)); /* 15.2.10.5.4  */
-  mrb_define_method(mrb, s, "=~",              noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.5  */
+
+  mrb_define_method(mrb, s, "<=>",             mrb_str_cmp_m,           MRB_ARGS_REQ(1)); /* 15.2.10.5.1  */
+  mrb_define_method(mrb, s, "==",              mrb_str_equal_m,         MRB_ARGS_REQ(1)); /* 15.2.10.5.2  */
+  mrb_define_method(mrb, s, "+",               mrb_str_plus_m,          MRB_ARGS_REQ(1)); /* 15.2.10.5.4  */
+  mrb_define_method(mrb, s, "*",               mrb_str_times,           MRB_ARGS_REQ(1)); /* 15.2.10.5.5  */
   mrb_define_method(mrb, s, "[]",              mrb_str_aref_m,          MRB_ARGS_ANY());  /* 15.2.10.5.6  */
   mrb_define_method(mrb, s, "capitalize",      mrb_str_capitalize,      MRB_ARGS_NONE()); /* 15.2.10.5.7  */
   mrb_define_method(mrb, s, "capitalize!",     mrb_str_capitalize_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.8  */
@@ -2547,31 +2506,25 @@ mrb_init_string(mrb_state *mrb)
   mrb_define_method(mrb, s, "empty?",          mrb_str_empty_p,         MRB_ARGS_NONE()); /* 15.2.10.5.16 */
   mrb_define_method(mrb, s, "eql?",            mrb_str_eql,             MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */
 
-  // NOTE: Regexp not implemented
-  mrb_define_method(mrb, s, "gsub",            noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.18 */
-  mrb_define_method(mrb, s, "gsub!",           noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.19 */
-
   mrb_define_method(mrb, s, "hash",            mrb_str_hash_m,          MRB_ARGS_REQ(1)); /* 15.2.10.5.20 */
   mrb_define_method(mrb, s, "include?",        mrb_str_include,         MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */
   mrb_define_method(mrb, s, "index",           mrb_str_index_m,         MRB_ARGS_ANY());  /* 15.2.10.5.22 */
   mrb_define_method(mrb, s, "initialize",      mrb_str_init,            MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */
   mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace,         MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */
   mrb_define_method(mrb, s, "intern",          mrb_str_intern,          MRB_ARGS_NONE()); /* 15.2.10.5.25 */
-  mrb_define_method(mrb, s, "match",           noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.27 */
+  mrb_define_method(mrb, s, "length",          mrb_str_size,            MRB_ARGS_NONE()); /* 15.2.10.5.26 */
   mrb_define_method(mrb, s, "replace",         mrb_str_replace,         MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */
   mrb_define_method(mrb, s, "reverse",         mrb_str_reverse,         MRB_ARGS_NONE()); /* 15.2.10.5.29 */
   mrb_define_method(mrb, s, "reverse!",        mrb_str_reverse_bang,    MRB_ARGS_NONE()); /* 15.2.10.5.30 */
   mrb_define_method(mrb, s, "rindex",          mrb_str_rindex_m,        MRB_ARGS_ANY());  /* 15.2.10.5.31 */
-  mrb_define_method(mrb, s, "scan",            noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.32 */
+  mrb_define_method(mrb, s, "size",            mrb_str_size,            MRB_ARGS_NONE()); /* 15.2.10.5.33 */
   mrb_define_method(mrb, s, "slice",           mrb_str_aref_m,          MRB_ARGS_ANY());  /* 15.2.10.5.34 */
   mrb_define_method(mrb, s, "split",           mrb_str_split_m,         MRB_ARGS_ANY());  /* 15.2.10.5.35 */
-  mrb_define_method(mrb, s, "sub",             noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.36 */
-  mrb_define_method(mrb, s, "sub!",            noregexp,                MRB_ARGS_REQ(1)); /* 15.2.10.5.37 */
 
-  mrb_define_method(mrb, s, "to_i",            mrb_str_to_i,            MRB_ARGS_ANY());  /* 15.2.10.5.38 */
-  mrb_define_method(mrb, s, "to_f",            mrb_str_to_f,            MRB_ARGS_NONE()); /* 15.2.10.5.39 */
+  mrb_define_method(mrb, s, "to_f",            mrb_str_to_f,            MRB_ARGS_NONE()); /* 15.2.10.5.38 */
+  mrb_define_method(mrb, s, "to_i",            mrb_str_to_i,            MRB_ARGS_ANY());  /* 15.2.10.5.39 */
   mrb_define_method(mrb, s, "to_s",            mrb_str_to_s,            MRB_ARGS_NONE()); /* 15.2.10.5.40 */
-  mrb_define_method(mrb, s, "to_str",          mrb_str_to_s,            MRB_ARGS_NONE()); /* 15.2.10.5.40 */
+  mrb_define_method(mrb, s, "to_str",          mrb_str_to_s,            MRB_ARGS_NONE());
   mrb_define_method(mrb, s, "to_sym",          mrb_str_intern,          MRB_ARGS_NONE()); /* 15.2.10.5.41 */
   mrb_define_method(mrb, s, "upcase",          mrb_str_upcase,          MRB_ARGS_REQ(1)); /* 15.2.10.5.42 */
   mrb_define_method(mrb, s, "upcase!",         mrb_str_upcase_bang,     MRB_ARGS_REQ(1)); /* 15.2.10.5.43 */