mRuby
view release on metacpan or search on metacpan
vendor/mruby/src/string.c view on Meta::CPAN
** string.c - String class
**
** See Copyright Notice in mruby.h
*/
#ifdef _MSC_VER
# define _CRT_NONSTDC_NO_DEPRECATE
#endif
#ifndef MRB_WITHOUT_FLOAT
#include <float.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/range.h>
#include <mruby/string.h>
#include <mruby/re.h>
typedef struct mrb_shared_string {
mrb_bool nofree : 1;
int refcnt;
char *ptr;
mrb_int len;
} mrb_shared_string;
const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
static struct RString*
str_new_static(mrb_state *mrb, const char *p, size_t len)
{
struct RString *s;
if (len >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
s = mrb_obj_alloc_string(mrb);
s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = 0; /* nofree */
s->as.heap.ptr = (char *)p;
s->flags = MRB_STR_NOFREE;
return s;
}
static struct RString*
str_new(mrb_state *mrb, const char *p, size_t len)
{
struct RString *s;
if (p && mrb_ro_data_p(p)) {
return str_new_static(mrb, p, len);
}
s = mrb_obj_alloc_string(mrb);
if (len <= RSTRING_EMBED_LEN_MAX) {
RSTR_SET_EMBED_FLAG(s);
RSTR_SET_EMBED_LEN(s, len);
if (p) {
memcpy(s->as.ary, p, len);
}
}
else {
if (len >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
}
s->as.heap.ptr = (char *)mrb_malloc(mrb, len+1);
s->as.heap.len = (mrb_int)len;
s->as.heap.aux.capa = (mrb_int)len;
if (p) {
memcpy(s->as.heap.ptr, p, len);
}
}
RSTR_PTR(s)[len] = '\0';
return s;
}
static inline void
str_with_class(mrb_state *mrb, struct RString *s, mrb_value obj)
{
s->c = mrb_str_ptr(obj)->c;
}
static mrb_value
mrb_str_new_empty(mrb_state *mrb, mrb_value str)
{
struct RString *s = str_new(mrb, 0, 0);
str_with_class(mrb, s, str);
return mrb_obj_value(s);
}
MRB_API mrb_value
mrb_str_new_capa(mrb_state *mrb, size_t capa)
{
struct RString *s;
s = mrb_obj_alloc_string(mrb);
if (capa >= MRB_INT_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
}
s->as.heap.len = 0;
s->as.heap.aux.capa = (mrb_int)capa;
s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1);
RSTR_PTR(s)[0] = '\0';
return mrb_obj_value(s);
}
#ifndef MRB_STR_BUF_MIN_SIZE
# define MRB_STR_BUF_MIN_SIZE 128
#endif
MRB_API mrb_value
mrb_str_buf_new(mrb_state *mrb, size_t capa)
{
if (capa < MRB_STR_BUF_MIN_SIZE) {
capa = MRB_STR_BUF_MIN_SIZE;
}
return mrb_str_new_capa(mrb, capa);
}
static void
resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
{
#if SIZE_MAX > MRB_INT_MAX
mrb_assert(capacity < MRB_INT_MAX);
#endif
if (RSTR_EMBED_P(s)) {
if (RSTRING_EMBED_LEN_MAX < capacity) {
char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
const mrb_int len = RSTR_EMBED_LEN(s);
memcpy(tmp, s->as.ary, len);
RSTR_UNSET_EMBED_FLAG(s);
s->as.heap.ptr = tmp;
s->as.heap.len = len;
s->as.heap.aux.capa = (mrb_int)capacity;
}
}
else {
s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
s->as.heap.aux.capa = (mrb_int)capacity;
}
}
MRB_API mrb_value
mrb_str_new(mrb_state *mrb, const char *p, size_t len)
{
return mrb_obj_value(str_new(mrb, p, len));
}
/*
* call-seq: (Caution! NULL string)
* String.new(str="") => new_str
*
* Returns a new string object containing a copy of <i>str</i>.
*/
MRB_API mrb_value
mrb_str_new_cstr(mrb_state *mrb, const char *p)
{
struct RString *s;
size_t len;
if (p) {
len = strlen(p);
}
else {
len = 0;
}
s = str_new(mrb, p, len);
return mrb_obj_value(s);
}
MRB_API mrb_value
mrb_str_new_static(mrb_state *mrb, const char *p, size_t len)
{
struct RString *s = str_new_static(mrb, p, len);
return mrb_obj_value(s);
}
static void
str_decref(mrb_state *mrb, mrb_shared_string *shared)
{
shared->refcnt--;
if (shared->refcnt == 0) {
if (!shared->nofree) {
mrb_free(mrb, shared->ptr);
}
mrb_free(mrb, shared);
}
}
void
mrb_gc_free_str(mrb_state *mrb, struct RString *str)
{
if (RSTR_EMBED_P(str))
/* no code */;
else if (RSTR_SHARED_P(str))
str_decref(mrb, str->as.heap.aux.shared);
else if (!RSTR_NOFREE_P(str) && !RSTR_FSHARED_P(str))
mrb_free(mrb, str->as.heap.ptr);
}
#ifdef MRB_UTF8_STRING
static const char utf8len_codepage[256] =
{
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,
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,
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,
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,
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,
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,
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,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
};
static mrb_int
utf8len(const char* p, const char* e)
{
mrb_int len;
mrb_int i;
len = utf8len_codepage[(unsigned char)*p];
if (p + len > e) return 1;
for (i = 1; i < len; ++i)
if ((p[i] & 0xc0) != 0x80)
return 1;
return len;
}
static mrb_int
utf8_strlen(mrb_value str, mrb_int len)
{
mrb_int total = 0;
char* p = RSTRING_PTR(str);
char* e = p;
if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
return RSTRING_LEN(str);
}
e += len < 0 ? RSTRING_LEN(str) : len;
while (p<e) {
p += utf8len(p, e);
total++;
}
if (RSTRING_LEN(str) == total) {
RSTRING(str)->flags |= MRB_STR_NO_UTF;
}
return total;
}
#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
/* map character index to byte offset index */
static mrb_int
chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
{
vendor/mruby/src/string.c view on Meta::CPAN
}
#define BYTES_ALIGN_CHECK(pos) if (pos < 0) return mrb_nil_value();
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
#define chars2bytes(p, off, ci) (ci)
#define bytes2chars(p, bi) (bi)
#define BYTES_ALIGN_CHECK(pos)
#endif
static inline mrb_int
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
const unsigned char *x = xs, *xe = xs + m;
const unsigned char *y = ys;
int i;
ptrdiff_t qstable[256];
/* Preprocessing */
for (i = 0; i < 256; ++i)
qstable[i] = m + 1;
for (; x < xe; ++x)
qstable[*x] = xe - x;
/* Searching */
for (; y + m <= ys + n; y += *(qstable + y[m])) {
if (*xs == *y && memcmp(xs, y, m) == 0)
return (mrb_int)(y - ys);
}
return -1;
}
static mrb_int
mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
{
const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0;
if (m > n) return -1;
else if (m == n) {
return memcmp(x0, y0, m) == 0 ? 0 : -1;
}
else if (m < 1) {
return 0;
}
else if (m == 1) {
const unsigned char *ys = (const unsigned char *)memchr(y, *x, n);
if (ys)
return (mrb_int)(ys - y);
else
return -1;
}
return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
}
static void
str_make_shared(mrb_state *mrb, struct RString *orig, struct RString *s)
{
mrb_shared_string *shared;
mrb_int len = RSTR_LEN(orig);
mrb_assert(!RSTR_EMBED_P(orig));
if (RSTR_SHARED_P(orig)) {
shared = orig->as.heap.aux.shared;
shared->refcnt++;
s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = len;
s->as.heap.aux.shared = shared;
RSTR_SET_SHARED_FLAG(s);
RSTR_UNSET_EMBED_FLAG(s);
}
else if (RSTR_FSHARED_P(orig)) {
struct RString *fs;
fs = orig->as.heap.aux.fshared;
s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = len;
s->as.heap.aux.fshared = fs;
RSTR_SET_FSHARED_FLAG(s);
RSTR_UNSET_EMBED_FLAG(s);
}
else if (MRB_FROZEN_P(orig) && !RSTR_POOL_P(orig)) {
s->as.heap.ptr = orig->as.heap.ptr;
s->as.heap.len = len;
s->as.heap.aux.fshared = orig;
RSTR_SET_FSHARED_FLAG(s);
RSTR_UNSET_EMBED_FLAG(s);
}
else {
shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
shared->refcnt = 2;
shared->nofree = !!RSTR_NOFREE_P(orig);
if (!shared->nofree && orig->as.heap.aux.capa > orig->as.heap.len) {
shared->ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
orig->as.heap.ptr = shared->ptr;
}
else {
shared->ptr = orig->as.heap.ptr;
}
orig->as.heap.aux.shared = shared;
RSTR_SET_SHARED_FLAG(orig);
shared->len = len;
s->as.heap.aux.shared = shared;
s->as.heap.ptr = shared->ptr;
s->as.heap.len = len;
RSTR_SET_SHARED_FLAG(s);
RSTR_UNSET_EMBED_FLAG(s);
}
}
static mrb_value
byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
struct RString *orig, *s;
orig = mrb_str_ptr(str);
if (RSTR_EMBED_P(orig) || RSTR_LEN(orig) == 0 || len <= RSTRING_EMBED_LEN_MAX) {
s = str_new(mrb, RSTR_PTR(orig)+beg, len);
}
else {
s = mrb_obj_alloc_string(mrb);
str_make_shared(mrb, orig, s);
s->as.heap.ptr += beg;
s->as.heap.len = len;
}
return mrb_obj_value(s);
}
#ifdef MRB_UTF8_STRING
static inline mrb_value
str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
beg = chars2bytes(str, 0, beg);
len = chars2bytes(str, beg, len);
return byte_subseq(mrb, str, beg, len);
}
#else
#define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len)
#endif
static mrb_value
str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
mrb_int clen = RSTRING_CHAR_LEN(str);
if (len < 0) return mrb_nil_value();
if (clen == 0) {
len = 0;
}
else if (beg < 0) {
beg = clen + beg;
}
if (beg > clen) return mrb_nil_value();
if (beg < 0) {
beg += clen;
if (beg < 0) return mrb_nil_value();
}
if (len > clen - beg)
len = clen - beg;
if (len <= 0) {
len = 0;
}
return str_subseq(mrb, str, beg, len);
}
MRB_API mrb_int
mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset)
{
mrb_int pos;
char *s;
mrb_int len;
len = RSTRING_LEN(str);
if (offset < 0) {
offset += len;
if (offset < 0) return -1;
}
if (len - offset < slen) return -1;
s = RSTRING_PTR(str);
if (offset) {
s += offset;
}
if (slen == 0) return offset;
/* need proceed one character at a time */
len = RSTRING_LEN(str) - offset;
pos = mrb_memsearch(sptr, slen, s, len);
if (pos < 0) return pos;
return pos + offset;
}
static mrb_int
str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
{
const char *ptr;
mrb_int len;
ptr = RSTRING_PTR(str2);
len = RSTRING_LEN(str2);
return mrb_str_index(mrb, str, ptr, len, offset);
}
static void
check_frozen(mrb_state *mrb, struct RString *s)
{
if (MRB_FROZEN_P(s)) {
mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen string");
}
}
static mrb_value
str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
mrb_int len;
check_frozen(mrb, s1);
if (s1 == s2) return mrb_obj_value(s1);
s1->flags &= ~MRB_STR_NO_UTF;
s1->flags |= s2->flags&MRB_STR_NO_UTF;
len = RSTR_LEN(s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
RSTR_UNSET_SHARED_FLAG(s1);
}
else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1) && !RSTR_FSHARED_P(s1)
&& s1->as.heap.ptr) {
mrb_free(mrb, s1->as.heap.ptr);
}
RSTR_UNSET_FSHARED_FLAG(s1);
RSTR_UNSET_NOFREE_FLAG(s1);
if (len <= RSTRING_EMBED_LEN_MAX) {
RSTR_UNSET_SHARED_FLAG(s1);
RSTR_UNSET_FSHARED_FLAG(s1);
RSTR_SET_EMBED_FLAG(s1);
memcpy(s1->as.ary, RSTR_PTR(s2), len);
RSTR_SET_EMBED_LEN(s1, len);
}
else {
str_make_shared(mrb, s2, s1);
}
return mrb_obj_value(s1);
}
static mrb_int
str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
{
char *s, *sbeg, *t;
struct RString *ps = mrb_str_ptr(str);
mrb_int len = RSTRING_LEN(sub);
/* substring longer than string */
if (RSTR_LEN(ps) < len) return -1;
if (RSTR_LEN(ps) - pos < len) {
pos = RSTR_LEN(ps) - len;
}
sbeg = RSTR_PTR(ps);
s = RSTR_PTR(ps) + pos;
t = RSTRING_PTR(sub);
if (len) {
while (sbeg <= s) {
if (memcmp(s, t, len) == 0) {
return (mrb_int)(s - RSTR_PTR(ps));
}
s--;
}
return -1;
}
else {
return pos;
}
}
MRB_API mrb_int
mrb_str_strlen(mrb_state *mrb, struct RString *s)
{
mrb_int i, max = RSTR_LEN(s);
char *p = RSTR_PTR(s);
if (!p) return 0;
for (i=0; i<max; i++) {
if (p[i] == '\0') {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
}
}
return max;
}
#ifdef _WIN32
#include <windows.h>
char*
mrb_utf8_from_locale(const char *str, int len)
{
wchar_t* wcsp;
char* mbsp;
vendor/mruby/src/string.c view on Meta::CPAN
if (!mbsp) {
free(wcsp);
return NULL;
}
mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
mbsp[mbssize] = 0;
free(wcsp);
return mbsp;
}
char*
mrb_locale_from_utf8(const char *utf8, int len)
{
wchar_t* wcsp;
char* mbsp;
int mbssize, wcssize;
if (len == 0)
return strdup("");
if (len == -1)
len = (int)strlen(utf8);
wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
if (!wcsp)
return NULL;
wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1);
wcsp[wcssize] = 0;
mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
mbsp = (char*) malloc((mbssize + 1));
if (!mbsp) {
free(wcsp);
return NULL;
}
mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
mbsp[mbssize] = 0;
free(wcsp);
return mbsp;
}
#endif
MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
check_frozen(mrb, s);
s->flags &= ~MRB_STR_NO_UTF;
if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared;
if (shared->nofree == 0 && shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
s->as.heap.ptr = shared->ptr;
s->as.heap.aux.capa = shared->len;
RSTR_PTR(s)[s->as.heap.len] = '\0';
mrb_free(mrb, shared);
}
else {
char *ptr, *p;
mrb_int len;
p = RSTR_PTR(s);
len = s->as.heap.len;
if (len < RSTRING_EMBED_LEN_MAX) {
RSTR_SET_EMBED_FLAG(s);
RSTR_SET_EMBED_LEN(s, len);
ptr = RSTR_PTR(s);
}
else {
ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
s->as.heap.ptr = ptr;
s->as.heap.aux.capa = len;
}
if (p) {
memcpy(ptr, p, len);
}
ptr[len] = '\0';
str_decref(mrb, shared);
}
RSTR_UNSET_SHARED_FLAG(s);
return;
}
if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
char *p = s->as.heap.ptr;
mrb_int len = s->as.heap.len;
RSTR_UNSET_FSHARED_FLAG(s);
RSTR_UNSET_NOFREE_FLAG(s);
RSTR_UNSET_FSHARED_FLAG(s);
if (len < RSTRING_EMBED_LEN_MAX) {
RSTR_SET_EMBED_FLAG(s);
RSTR_SET_EMBED_LEN(s, len);
}
else {
s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
s->as.heap.aux.capa = len;
}
if (p) {
memcpy(RSTR_PTR(s), p, len);
}
RSTR_PTR(s)[len] = '\0';
return;
}
}
MRB_API mrb_value
mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
{
mrb_int slen;
struct RString *s = mrb_str_ptr(str);
mrb_str_modify(mrb, s);
slen = RSTR_LEN(s);
if (len != slen) {
if (slen < len || slen - len > 256) {
resize_capa(mrb, s, len);
}
RSTR_SET_LEN(s, len);
RSTR_PTR(s)[len] = '\0'; /* sentinel */
}
return str;
}
MRB_API char*
mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
{
struct RString *s;
if (!mrb_string_p(str0)) {
mrb_raise(mrb, E_TYPE_ERROR, "expected String");
}
s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
}
return RSTR_PTR(s);
}
/*
* call-seq: (Caution! String("abcd") change)
* String("abcdefg") = String("abcd") + String("efg")
*
* Returns a new string object containing a copy of <i>str</i>.
*/
MRB_API void
mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
{
if (!mrb_string_p(other)) {
other = mrb_str_to_str(mrb, other);
}
mrb_str_cat_str(mrb, self, other);
vendor/mruby/src/string.c view on Meta::CPAN
switch (c) {
case '\n': cc = 'n'; break;
case '\r': cc = 'r'; break;
case '\t': cc = 't'; break;
case '\f': cc = 'f'; break;
case '\013': cc = 'v'; break;
case '\010': cc = 'b'; break;
case '\007': cc = 'a'; break;
case 033: cc = 'e'; break;
default: cc = 0; break;
}
if (cc) {
buf[0] = '\\';
buf[1] = (char)cc;
mrb_str_cat(mrb, result, buf, 2);
continue;
}
else {
buf[0] = '\\';
buf[3] = '0' + c % 8; c /= 8;
buf[2] = '0' + c % 8; c /= 8;
buf[1] = '0' + c % 8;
mrb_str_cat(mrb, result, buf, 4);
continue;
}
}
mrb_str_cat_lit(mrb, result, "\"");
return result;
}
/*
* call-seq:
* str.bytes -> array of fixnums
*
* Returns an array of bytes in _str_.
*
* str = "hello"
* str.bytes #=> [104, 101, 108, 108, 111]
*/
static mrb_value
mrb_str_bytes(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
mrb_value a = mrb_ary_new_capa(mrb, RSTR_LEN(s));
unsigned char *p = (unsigned char *)(RSTR_PTR(s)), *pend = p + RSTR_LEN(s);
while (p < pend) {
mrb_ary_push(mrb, a, mrb_fixnum_value(p[0]));
p++;
}
return a;
}
/* ---------------------------*/
void
mrb_init_string(mrb_state *mrb)
{
struct RClass *s;
mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string");
mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
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_NONE()); /* 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_NONE()); /* 15.2.10.5.11 */
mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_NONE()); /* 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_NONE()); /* 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, 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 */
#ifndef MRB_WITHOUT_FLOAT
mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */
#endif
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_NONE()); /* 15.2.10.5.42 */
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 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());
}
#ifndef MRB_WITHOUT_FLOAT
/*
* Source code for the "strtod" library procedure.
*
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
( run in 0.522 second using v1.01-cache-2.11-cpan-71847e10f99 )