*/
#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>
#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
-#include "mruby/numeric.h"
#include "mruby/range.h"
#include "mruby/string.h"
#include "re.h"
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+typedef struct mrb_shared_string {
+ mrb_bool nofree;
+ int refcnt;
+ char *ptr;
+ mrb_int len;
+} mrb_shared_string;
+
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);
#define RESIZE_CAPA(s,capacity) do {\
s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\
s->aux.capa = capacity;\
-} while (0)
+} while(0)
-void
-mrb_str_decref(mrb_state *mrb, mrb_shared_string *shared)
+static void
+str_decref(mrb_state *mrb, mrb_shared_string *shared)
{
shared->refcnt--;
if (shared->refcnt == 0) {
- mrb_free(mrb, shared->ptr);
+ if (!shared->nofree) {
+ mrb_free(mrb, shared->ptr);
+ }
mrb_free(mrb, shared);
}
}
-static void
-str_modify(mrb_state *mrb, struct RString *s)
+void
+mrb_str_modify(mrb_state *mrb, struct RString *s)
{
if (s->flags & MRB_STR_SHARED) {
mrb_shared_string *shared = s->aux.shared;
@@ -51,6 +54,7 @@ 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 {
@@ -63,44 +67,46 @@ 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;
- mrb_str_decref(mrb, shared);
+ str_decref(mrb, shared);
}
s->flags &= ~MRB_STR_SHARED;
+ return;
+ }
+ if (s->flags & MRB_STR_NOFREE) {
+ char *p = s->ptr;
+
+ s->ptr = (char *)mrb_malloc(mrb, (size_t)s->len+1);
+ if (p) {
+ memcpy(s->ptr, p, s->len);
+ }
+ s->ptr[s->len] = '\0';
+ s->aux.capa = s->len;
+ s->flags &= ~MRB_STR_NOFREE;
+ return;
}
}
mrb_value
-mrb_str_resize(mrb_state *mrb, mrb_value str, int len)
+mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
{
int slen;
struct RString *s = mrb_str_ptr(str);
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
slen = s->len;
if (len != slen) {
- if (slen < len || slen -len > 1024) {
- s->ptr = (char *)mrb_realloc(mrb, s->ptr, len+1);
+ if (slen < len || slen - len > 256) {
+ RESIZE_CAPA(s, len);
}
- s->aux.capa = len;
s->len = len;
s->ptr[len] = '\0'; /* sentinel */
}
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 */
@@ -111,14 +117,14 @@ mrb_str_offset(mrb_state *mrb, mrb_value str, int pos)
}
static struct RString*
-str_new(mrb_state *mrb, const char *p, int len)
+str_new(mrb_state *mrb, const char *p, mrb_int len)
{
struct RString *s;
s = mrb_obj_alloc_string(mrb);
s->len = len;
s->aux.capa = len;
- s->ptr = (char *)mrb_malloc(mrb, len+1);
+ s->ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
if (p) {
memcpy(s->ptr, p, len);
}
@@ -146,7 +152,7 @@ mrb_str_new_empty(mrb_state *mrb, mrb_value str)
#endif
mrb_value
-mrb_str_buf_new(mrb_state *mrb, int capa)
+mrb_str_buf_new(mrb_state *mrb, mrb_int capa)
{
struct RString *s;
@@ -170,13 +176,13 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
mrb_int total;
ptrdiff_t off = -1;
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
if (ptr >= s->ptr && ptr <= s->ptr + s->len) {
off = ptr - s->ptr;
}
if (len == 0) return;
capa = s->aux.capa;
- if (s->len >= MRB_INT_MAX - len) {
+ if (s->len >= MRB_INT_MAX - (mrb_int)len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big");
}
total = s->len+len;
@@ -238,32 +244,47 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p)
len = 0;
}
+ s = str_new(mrb, p, len);
+
+ return mrb_obj_value(s);
+}
+
+mrb_value
+mrb_str_new_static(mrb_state *mrb, const char *p, size_t len)
+{
+ struct RString *s;
+
s = mrb_obj_alloc_string(mrb);
- s->ptr = (char *)mrb_malloc(mrb, len+1);
- if (p) {
- memcpy(s->ptr, p, len);
- }
- s->ptr[len] = 0;
s->len = len;
- s->aux.capa = len;
-
+ s->aux.capa = 0; /* nofree */
+ s->ptr = (char *)p;
+ s->flags = MRB_STR_NOFREE;
return mrb_obj_value(s);
}
+void
+mrb_gc_free_str(mrb_state *mrb, struct RString *str)
+{
+ if (str->flags & MRB_STR_SHARED)
+ str_decref(mrb, str->aux.shared);
+ else if ((str->flags & MRB_STR_NOFREE) == 0)
+ mrb_free(mrb, str->ptr);
+}
+
char *
mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
{
- mrb_value str;
+ struct RString *s;
if (!mrb_string_p(str0)) {
mrb_raise(mrb, E_TYPE_ERROR, "expected String");
}
- str = mrb_str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
- if (strlen(RSTRING_PTR(str)) != RSTRING_LEN(str)) {
+ s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
+ if ((strlen(s->ptr) ^ s->len) != 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
}
- return RSTRING_PTR(str);
+ return s->ptr;
}
static void
@@ -273,11 +294,19 @@ str_make_shared(mrb_state *mrb, struct RString *s)
mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
shared->refcnt = 1;
- if (s->aux.capa > s->len) {
- s->ptr = shared->ptr = (char *)mrb_realloc(mrb, s->ptr, s->len+1);
+ if (s->flags & MRB_STR_NOFREE) {
+ shared->nofree = TRUE;
+ shared->ptr = s->ptr;
+ s->flags &= ~MRB_STR_NOFREE;
}
else {
- shared->ptr = s->ptr;
+ shared->nofree = FALSE;
+ if (s->aux.capa > s->len) {
+ s->ptr = shared->ptr = (char *)mrb_realloc(mrb, s->ptr, s->len+1);
+ }
+ else {
+ shared->ptr = s->ptr;
+ }
}
shared->len = s->len;
s->aux.shared = shared;
@@ -286,35 +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, mrb_str_ptr(str));
- }
- shared = orig->aux.shared;
- shared->refcnt++;
- s->ptr = shared->ptr;
- s->len = shared->len;
- s->aux.capa = 0;
- s->aux.shared = shared;
- s->flags |= MRB_STR_SHARED;
-
- return mrb_obj_value(s);
-}
-
-/*
* call-seq:
* char* str = String("abcd"), len=strlen("abcd")
*
mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
{
struct RString *s1 = mrb_str_ptr(self), *s2;
- int len;
+ mrb_int len;
- str_modify(mrb, s1);
+ mrb_str_modify(mrb, s1);
if (!mrb_string_p(other)) {
other = mrb_str_to_str(mrb, other);
}
@@ -354,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';
}
/*
@@ -529,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 {
@@ -551,25 +551,24 @@ 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 size_t len = RSTRING_LEN(str1);
+ const mrb_int len = RSTRING_LEN(str1);
- /* assert(SIZE_MAX >= MRB_INT_MAX) */
if (len != RSTRING_LEN(str2)) return FALSE;
- if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0)
+ if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), (size_t)len) == 0)
return TRUE;
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);
@@ -633,7 +632,7 @@ noregexp(mrb_state *mrb, mrb_value self)
static void
regexp_check(mrb_state *mrb, mrb_value obj)
{
- if (!strcmp(mrb_obj_classname(mrb, obj), REGEXP_CLASS)) {
+ if (!memcmp(mrb_obj_classname(mrb, obj), REGEXP_CLASS, sizeof(REGEXP_CLASS) - 1)) {
noregexp(mrb, obj);
}
}
@@ -742,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();
@@ -845,7 +842,7 @@ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
int modify = 0;
struct RString *s = mrb_str_ptr(str);
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
if (s->len == 0 || !s->ptr) return mrb_nil_value();
p = s->ptr; pend = s->ptr + s->len;
if (ISLOWER(*p)) {
@@ -902,7 +899,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
mrb_int len;
struct RString *s = mrb_str_ptr(str);
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
len = s->len;
if (mrb_get_args(mrb, "|S", &rs) == 0) {
if (len == 0) return mrb_nil_value();
@@ -1001,7 +998,7 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
if (s->len > 0) {
int len;
len = s->len - 1;
@@ -1059,7 +1056,7 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
int modify = 0;
struct RString *s = mrb_str_ptr(str);
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
p = s->ptr;
pend = s->ptr + s->len;
while (p < pend) {
@@ -1234,8 +1231,8 @@ 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) {
- include_p = memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self));
+ if (mrb_fixnum_p(str2)) {
+ include_p = (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)) != NULL);
}
else {
str2 = mrb_str_to_str(mrb, str2);
@@ -1337,7 +1334,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
if (s2->flags & MRB_STR_SHARED) {
L_SHARE:
if (s1->flags & MRB_STR_SHARED){
- mrb_str_decref(mrb, s1->aux.shared);
+ str_decref(mrb, s1->aux.shared);
}
else {
mrb_free(mrb, s1->ptr);
@@ -1354,7 +1351,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
}
else {
if (s1->flags & MRB_STR_SHARED) {
- mrb_str_decref(mrb, s1->aux.shared);
+ str_decref(mrb, s1->aux.shared);
s1->flags &= ~MRB_STR_SHARED;
s1->ptr = (char *)mrb_malloc(mrb, s2->len+1);
}
@@ -1456,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;
@@ -1481,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");
@@ -1529,7 +1532,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
char *p, *e;
char c;
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
if (s->len > 1) {
p = s->ptr;
e = p + s->len - 1;
@@ -2171,7 +2174,7 @@ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck)
static mrb_value
mrb_str_to_f(mrb_state *mrb, mrb_value self)
{
- return mrb_float_value(mrb_str_to_dbl(mrb, self, 0/*Qfalse*/));
+ return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, 0/*Qfalse*/));
}
/* 15.2.10.5.40 */
@@ -2206,7 +2209,7 @@ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str)
char *p, *pend;
int modify = 0;
- str_modify(mrb, s);
+ mrb_str_modify(mrb, s);
p = RSTRING_PTR(str);
pend = RSTRING_END(str);
while (p < pend) {
@@ -2304,62 +2307,57 @@ 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;
}
else {
- mrb_value octstr;
- mrb_value chr;
- const char *ptr;
- int len;
- chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fixnum_to_str(mrb, chr, 8);
- ptr = mrb_str_body(octstr, &len);
- memcpy(q, "\\000", 4);
- memcpy(q + 4 - len, ptr, len);
- q += 4;
+ *q++ = '\\';
+ q[2] = '0' + c % 8; c /= 8;
+ q[1] = '0' + c % 8; c /= 8;
+ q[0] = '0' + c % 8;
+ q += 3;
}
}
}
@@ -2368,9 +2366,9 @@ mrb_str_dump(mrb_state *mrb, mrb_value str)
}
mrb_value
-mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len)
+mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
{
- if (len < 0) {
+ if ((mrb_int)len < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)");
}
str_buf_cat(mrb, mrb_str_ptr(str), ptr, len);
@@ -2412,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))) {
@@ -2443,15 +2441,10 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
continue;
}
else {
- mrb_value octstr;
- mrb_value chr;
- const char *ptr;
- int len;
- chr = mrb_fixnum_value(c & 0xff);
- octstr = mrb_fixnum_to_str(mrb, chr, 8);
- ptr = mrb_str_body(octstr, &len);
- memcpy(buf, "\\000", 4);
- memcpy(buf + 4 - len, ptr, len);
+ buf[0] = '\\';
+ buf[3] = '0' + c % 8; c /= 8;
+ buf[2] = '0' + c % 8; c /= 8;
+ buf[1] = '0' + c % 8;
mrb_str_buf_cat(mrb, result, buf, 4);
continue;
}
@@ -2494,54 +2487,47 @@ 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, ARGS_REQ(1)); /* 15.2.10.5.2 */
- mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, ARGS_NONE());
- mrb_define_method(mrb, s, "size", mrb_str_size, ARGS_NONE()); /* 15.2.10.5.33 */
- mrb_define_method(mrb, s, "length", mrb_str_size, ARGS_NONE()); /* 15.2.10.5.26 */
- mrb_define_method(mrb, s, "*", mrb_str_times, ARGS_REQ(1)); /* 15.2.10.5.1 */
- mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, ARGS_REQ(1)); /* 15.2.10.5.3 */
- mrb_define_method(mrb, s, "==", mrb_str_equal_m, ARGS_REQ(1)); /* 15.2.10.5.4 */
- mrb_define_method(mrb, s, "=~", noregexp, ARGS_REQ(1)); /* 15.2.10.5.5 */
- mrb_define_method(mrb, s, "[]", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.6 */
- mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, ARGS_NONE()); /* 15.2.10.5.7 */
- mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, ARGS_REQ(1)); /* 15.2.10.5.8 */
- mrb_define_method(mrb, s, "chomp", mrb_str_chomp, ARGS_ANY()); /* 15.2.10.5.9 */
- mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, ARGS_ANY()); /* 15.2.10.5.10 */
- mrb_define_method(mrb, s, "chop", mrb_str_chop, ARGS_REQ(1)); /* 15.2.10.5.11 */
- mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, ARGS_REQ(1)); /* 15.2.10.5.12 */
- mrb_define_method(mrb, s, "downcase", mrb_str_downcase, ARGS_NONE()); /* 15.2.10.5.13 */
- mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, ARGS_NONE()); /* 15.2.10.5.14 */
- mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, ARGS_NONE()); /* 15.2.10.5.16 */
- mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */
-
- // NOTE: Regexp not implemented
- mrb_define_method(mrb, s, "gsub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.18 */
- mrb_define_method(mrb, s, "gsub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.19 */
-
- mrb_define_method(mrb, s, "hash", mrb_str_hash_m, ARGS_REQ(1)); /* 15.2.10.5.20 */
- mrb_define_method(mrb, s, "include?", mrb_str_include, ARGS_REQ(1)); /* 15.2.10.5.21 */
- mrb_define_method(mrb, s, "index", mrb_str_index_m, ARGS_ANY()); /* 15.2.10.5.22 */
- mrb_define_method(mrb, s, "initialize", mrb_str_init, ARGS_REQ(1)); /* 15.2.10.5.23 */
- mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.24 */
- mrb_define_method(mrb, s, "intern", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.25 */
- mrb_define_method(mrb, s, "match", noregexp, ARGS_REQ(1)); /* 15.2.10.5.27 */
- mrb_define_method(mrb, s, "replace", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.28 */
- mrb_define_method(mrb, s, "reverse", mrb_str_reverse, ARGS_NONE()); /* 15.2.10.5.29 */
- mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, ARGS_NONE()); /* 15.2.10.5.30 */
- mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, ARGS_ANY()); /* 15.2.10.5.31 */
- mrb_define_method(mrb, s, "scan", noregexp, ARGS_REQ(1)); /* 15.2.10.5.32 */
- mrb_define_method(mrb, s, "slice", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.34 */
- mrb_define_method(mrb, s, "split", mrb_str_split_m, ARGS_ANY()); /* 15.2.10.5.35 */
- mrb_define_method(mrb, s, "sub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.36 */
- mrb_define_method(mrb, s, "sub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.37 */
-
- mrb_define_method(mrb, s, "to_i", mrb_str_to_i, ARGS_ANY()); /* 15.2.10.5.38 */
- mrb_define_method(mrb, s, "to_f", mrb_str_to_f, ARGS_NONE()); /* 15.2.10.5.39 */
- mrb_define_method(mrb, s, "to_s", mrb_str_to_s, ARGS_NONE()); /* 15.2.10.5.40 */
- mrb_define_method(mrb, s, "to_str", mrb_str_to_s, ARGS_NONE()); /* 15.2.10.5.40 */
- mrb_define_method(mrb, s, "to_sym", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.41 */
- mrb_define_method(mrb, s, "upcase", mrb_str_upcase, ARGS_REQ(1)); /* 15.2.10.5.42 */
- mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, ARGS_REQ(1)); /* 15.2.10.5.43 */
- mrb_define_method(mrb, s, "inspect", mrb_str_inspect, ARGS_NONE()); /* 15.2.10.5.46(x) */
- mrb_define_method(mrb, s, "bytes", mrb_str_bytes, ARGS_NONE());
+
+ mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE());
+
+ 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 */
+ mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */
+ mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */
+ mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_REQ(1)); /* 15.2.10.5.11 */
+ mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.12 */
+ mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */
+ mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */
+ 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 */
+
+ 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, "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, "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, "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());
+ 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 */
+ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
+ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE());
}