mRuby

 view release on metacpan or  search on metacpan

vendor/mruby/include/mruby/array.h  view on Meta::CPAN

 */
MRB_BEGIN_DECL


typedef struct mrb_shared_array {
  int refcnt;
  mrb_int len;
  mrb_value *ptr;
} mrb_shared_array;

#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
struct RArray {
  MRB_OBJECT_HEADER;
  union {
    struct {
      mrb_int len;
      union {
        mrb_int capa;
        mrb_shared_array *shared;
      } aux;
      mrb_value *ptr;
    } heap;
    mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
  } as;
};

#define mrb_ary_ptr(v)    ((struct RArray*)(mrb_ptr(v)))
#define mrb_ary_value(p)  mrb_obj_value((void*)(p))
#define RARRAY(v)  ((struct RArray*)(mrb_ptr(v)))

#define MRB_ARY_EMBED_MASK  7
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))

#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
#define ARY_SET_LEN(a,n) do {\
  if (ARY_EMBED_P(a)) {\
    mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
    ARY_SET_EMBED_LEN(a,n);\
  }\
  else\
    (a)->as.heap.len = (n);\
} while (0)
#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
#define MRB_ARY_SHARED      256
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED)

void mrb_ary_decref(mrb_state*, mrb_shared_array*);
MRB_API void mrb_ary_modify(mrb_state*, struct RArray*);
MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);

/*

vendor/mruby/include/mruby/string.h  view on Meta::CPAN


#include "common.h"

/**
 * String class
 */
MRB_BEGIN_DECL

extern const char mrb_digitmap[];

#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1))

struct RString {
  MRB_OBJECT_HEADER;
  union {
    struct {
      mrb_int len;
      union {
        mrb_int capa;
        struct mrb_shared_string *shared;
        struct RString *fshared;
      } aux;
      char *ptr;
    } heap;
    char ary[RSTRING_EMBED_LEN_MAX + 1];
  } as;
};

#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
#define RSTR_SET_EMBED_LEN(s, n) do {\
  size_t tmp_n = (n);\
  s->flags &= ~MRB_STR_EMBED_LEN_MASK;\
  s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
} while (0)
#define RSTR_SET_LEN(s, n) do {\
  if (RSTR_EMBED_P(s)) {\
    RSTR_SET_EMBED_LEN((s),(n));\
  }\
  else {\
    s->as.heap.len = (mrb_int)(n);\
  }\
} while (0)
#define RSTR_EMBED_LEN(s)\
  (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr)
#define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len)
#define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa)

#define RSTR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED)
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)

#define RSTR_FSHARED_P(s) ((s)->flags & MRB_STR_FSHARED)
#define RSTR_SET_FSHARED_FLAG(s) ((s)->flags |= MRB_STR_FSHARED)
#define RSTR_UNSET_FSHARED_FLAG(s) ((s)->flags &= ~MRB_STR_FSHARED)

#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)

vendor/mruby/include/mruby/string.h  view on Meta::CPAN


#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL)
#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL)

/*
 * Returns a pointer from a Ruby string
 */
#define mrb_str_ptr(s)       ((struct RString*)(mrb_ptr(s)))
#define RSTRING(s)           mrb_str_ptr(s)
#define RSTRING_PTR(s)       RSTR_PTR(RSTRING(s))
#define RSTRING_EMBED_LEN(s) RSTR_EMBED_LEN(RSTRING(s))
#define RSTRING_LEN(s)       RSTR_LEN(RSTRING(s))
#define RSTRING_CAPA(s)      RSTR_CAPA(RSTRING(s))
#define RSTRING_END(s)       (RSTRING_PTR(s) + RSTRING_LEN(s))
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);

#define MRB_STR_SHARED    1
#define MRB_STR_FSHARED   2
#define MRB_STR_NOFREE    4
#define MRB_STR_POOL      8
#define MRB_STR_NO_UTF   16
#define MRB_STR_EMBED    32
#define MRB_STR_EMBED_LEN_MASK 0x7c0
#define MRB_STR_EMBED_LEN_SHIFT 6

void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*);

/*
 * Finds the index of a substring in a string
 */
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);

vendor/mruby/mrbgems/mruby-sprintf/src/sprintf.c  view on Meta::CPAN

      case 'p':
  format_s:
      {
        mrb_value arg = GETARG();
        mrb_int len;
        mrb_int slen;

        if (*p == 'p') arg = mrb_inspect(mrb, arg);
        str = mrb_obj_as_string(mrb, arg);
        len = RSTRING_LEN(str);
        if (RSTRING(result)->flags & MRB_STR_EMBED) {
          mrb_int tmp_n = len;
          RSTRING(result)->flags &= ~MRB_STR_EMBED_LEN_MASK;
          RSTRING(result)->flags |= tmp_n << MRB_STR_EMBED_LEN_SHIFT;
        }
        else {
          RSTRING(result)->as.heap.len = blen;
        }
        if (flags&(FPREC|FWIDTH)) {
          slen = RSTRING_LEN(str);
          if (slen < 0) {
            mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence");
          }
          if ((flags&FPREC) && (prec < slen)) {

vendor/mruby/src/array.c  view on Meta::CPAN

{
  struct RArray *a;
  size_t blen;

  if (capa > ARY_MAX_SIZE) {
    mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
  }
  blen = capa * sizeof(mrb_value);

  a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
  if (capa <= MRB_ARY_EMBED_LEN_MAX) {
    ARY_SET_EMBED_LEN(a, 0);
  }
  else {
    a->as.heap.ptr = (mrb_value *)mrb_malloc(mrb, blen);
    a->as.heap.aux.capa = capa;
    a->as.heap.len = 0;
  }

  return a;
}

vendor/mruby/src/array.c  view on Meta::CPAN

MRB_API void
mrb_ary_modify(mrb_state *mrb, struct RArray* a)
{
  mrb_write_barrier(mrb, (struct RBasic*)a);
  ary_modify(mrb, a);
}

static void
ary_make_shared(mrb_state *mrb, struct RArray *a)
{
  if (!ARY_SHARED_P(a) && !ARY_EMBED_P(a)) {
    mrb_shared_array *shared = (mrb_shared_array *)mrb_malloc(mrb, sizeof(mrb_shared_array));
    mrb_value *ptr = a->as.heap.ptr;
    mrb_int len = a->as.heap.len;

    shared->refcnt = 1;
    if (a->as.heap.aux.capa > len) {
      a->as.heap.ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, ptr, sizeof(mrb_value)*len+1);
    }
    else {
      shared->ptr = ptr;

vendor/mruby/src/array.c  view on Meta::CPAN

      capa *= 2;
    }
    else {
      capa = len;
    }
  }
  if (capa < len || capa > ARY_MAX_SIZE) {
    goto size_error;
  }

  if (ARY_EMBED_P(a)) {
    mrb_value *ptr = ARY_EMBED_PTR(a);
    mrb_int len = ARY_EMBED_LEN(a);
    mrb_value *expanded_ptr = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*capa);

    ARY_UNSET_EMBED_FLAG(a);
    array_copy(expanded_ptr, ptr, len);
    a->as.heap.len = len;
    a->as.heap.aux.capa = capa;
    a->as.heap.ptr = expanded_ptr;
  }
  else if (capa > a->as.heap.aux.capa) {
    mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->as.heap.ptr, sizeof(mrb_value)*capa);

    a->as.heap.aux.capa = capa;
    a->as.heap.ptr = expanded_ptr;
  }
}

static void
ary_shrink_capa(mrb_state *mrb, struct RArray *a)
{
  
  mrb_int capa;

  if (ARY_EMBED_P(a)) return;

  capa = a->as.heap.aux.capa;
  if (capa < ARY_DEFAULT_LEN * 2) return;
  if (capa <= a->as.heap.len * ARY_SHRINK_RATIO) return;

  do {
    capa /= 2;
    if (capa < ARY_DEFAULT_LEN) {
      capa = ARY_DEFAULT_LEN;
      break;

vendor/mruby/src/array.c  view on Meta::CPAN

MRB_API mrb_value
mrb_ary_clear(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  ary_modify(mrb, a);
  if (ARY_SHARED_P(a)) {
    mrb_ary_decref(mrb, a->as.heap.aux.shared);
    ARY_UNSET_SHARED_FLAG(a);
  }
  else if (!ARY_EMBED_P(a)){
    mrb_free(mrb, a->as.heap.ptr);
  }
  ARY_SET_EMBED_LEN(a, 0);

  return self;
}

static mrb_value
mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
{
  struct RArray *a = mrb_ary_ptr(self);

  return mrb_bool_value(ARY_LEN(a) == 0);

vendor/mruby/src/gc.c  view on Meta::CPAN

          }
        }
        mrb_free_context(mrb, c);
      }
    }
    break;

  case MRB_TT_ARRAY:
    if (ARY_SHARED_P(obj))
      mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared);
    else if (!ARY_EMBED_P(obj))
      mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr);
    break;

  case MRB_TT_HASH:
    mrb_gc_free_iv(mrb, (struct RObject*)obj);
    mrb_gc_free_hash(mrb, (struct RHash*)obj);
    break;

  case MRB_TT_STRING:
    mrb_gc_free_str(mrb, (struct RString*)obj);

vendor/mruby/src/state.c  view on Meta::CPAN

  ns->c = mrb->string_class;

  if (RSTR_NOFREE_P(s)) {
    ns->flags = MRB_STR_NOFREE;
    ns->as.heap.ptr = s->as.heap.ptr;
    ns->as.heap.len = s->as.heap.len;
    ns->as.heap.aux.capa = 0;
  }
  else {
    ns->flags = 0;
    if (RSTR_EMBED_P(s)) {
      ptr = s->as.ary;
      len = RSTR_EMBED_LEN(s);
    }
    else {
      ptr = s->as.heap.ptr;
      len = s->as.heap.len;
    }

    if (len < RSTRING_EMBED_LEN_MAX) {
      RSTR_SET_EMBED_FLAG(ns);
      RSTR_SET_EMBED_LEN(ns, len);
      if (ptr) {
        memcpy(ns->as.ary, ptr, len);
      }
      ns->as.ary[len] = '\0';
    }
    else {
      ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
      ns->as.heap.len = len;
      ns->as.heap.aux.capa = len;
      if (ptr) {

vendor/mruby/src/string.c  view on Meta::CPAN


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;

vendor/mruby/src/string.c  view on Meta::CPAN

  }
  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;
  }
}

vendor/mruby/src/string.c  view on Meta::CPAN

    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] =
{

vendor/mruby/src/string.c  view on Meta::CPAN

  }
  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);
}

vendor/mruby/src/string.c  view on Meta::CPAN


  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)

vendor/mruby/src/string.c  view on Meta::CPAN

      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);
      }

vendor/mruby/src/string.c  view on Meta::CPAN

    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;

vendor/mruby/src/string.c  view on Meta::CPAN

  }
  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  */



( run in 1.096 second using v1.01-cache-2.11-cpan-71847e10f99 )