Beispiel #1
0
static VALUE
bubblebabble_str_new(VALUE str_digest)
{
    char *digest;
    size_t digest_len;
    VALUE str;
    char *p;
    size_t i, j, seed = 1;
    static const char vowels[] = {
        'a', 'e', 'i', 'o', 'u', 'y'
    };
    static const char consonants[] = {
        'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
        'p', 'r', 's', 't', 'v', 'z', 'x'
    };

    StringValue(str_digest);
    digest = RSTRING_PTR(str_digest);
    digest_len = RSTRING_LEN(str_digest);

    if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
	rb_raise(rb_eRuntimeError, "digest string too long");
    }

    str = rb_str_new(0, (digest_len | 1) * 3 + 2);
    p = RSTRING_PTR(str);

    i = j = 0;
    p[j++] = 'x';

    for (;;) {
        unsigned char byte1, byte2;

        if (i >= digest_len) {
            p[j++] = vowels[seed % 6];
            p[j++] = consonants[16];
            p[j++] = vowels[seed / 6];
            break;
        }

        byte1 = digest[i++];
        p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
        p[j++] = consonants[(byte1 >> 2) & 15];
        p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];

        if (i >= digest_len) {
            break;
        }

        byte2 = digest[i++];
        p[j++] = consonants[(byte2 >> 4) & 15];
        p[j++] = '-';
        p[j++] = consonants[byte2 & 15];

        seed = (seed * 5 + byte1 * 7 + byte2) % 36;
    }

    p[j] = 'x';

    return str;
}
Beispiel #2
0
static int
rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
{
    VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
    const char *f, *e;
    long i, len, elen, n;
    st_table *loading_tbl, *features_index;
    st_data_t data;
    int type;

    if (fn) *fn = 0;
    if (ext) {
	elen = strlen(ext);
	len = strlen(feature) - elen;
	type = rb ? 'r' : 's';
    }
    else {
	len = strlen(feature);
	elen = 0;
	type = 0;
    }
    features = get_loaded_features();
    features_index = get_loaded_features_index();

    st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
    /* We search `features` for an entry such that either
         "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
       for some j, or
         "#{features[i]}" == "#{feature}#{e}"
       Here `e` is an "allowed" extension -- either empty or one
       of the extensions accepted by IS_RBEXT, IS_SOEXT, or
       IS_DLEXT.  Further, if `ext && rb` then `IS_RBEXT(e)`,
       and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.

       If `expanded`, then only the latter form (without load_path[j])
       is accepted.  Otherwise either form is accepted, *unless* `ext`
       is false and an otherwise-matching entry of the first form is
       preceded by an entry of the form
         "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
       where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
       After a "distractor" entry of this form, only entries of the
       form "#{feature}#{e}" are accepted.

       In `rb_provide_feature()` and `get_loaded_features_index()` we
       maintain an invariant that the array `this_feature_index` will
       point to every entry in `features` which has the form
         "#{prefix}#{feature}#{e}"
       where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
       or ends in '/'.  This includes both match forms above, as well
       as any distractors, so we may ignore all other entries in `features`.
     */
    if (!NIL_P(this_feature_index)) {
	for (i = 0; ; i++) {
	    VALUE entry;
	    long index;
	    if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
		if (i >= RARRAY_LEN(this_feature_index)) break;
		entry = RARRAY_AREF(this_feature_index, i);
	    }
	    else {
		if (i > 0) break;
		entry = this_feature_index;
	    }
	    index = FIX2LONG(entry);

	    v = RARRAY_AREF(features, index);
	    f = StringValuePtr(v);
	    if ((n = RSTRING_LEN(v)) < len) continue;
	    if (strncmp(f, feature, len) != 0) {
		if (expanded) continue;
		if (!load_path) load_path = rb_get_expanded_load_path();
		if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
		    continue;
		expanded = 1;
		f += RSTRING_LEN(p) + 1;
	    }
	    if (!*(e = f + len)) {
		if (ext) continue;
		return 'u';
	    }
	    if (*e != '.') continue;
	    if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
		return 's';
	    }
	    if ((rb || !ext) && (IS_RBEXT(e))) {
		return 'r';
	    }
	}
    }

    loading_tbl = get_loading_table();
    if (loading_tbl) {
	f = 0;
	if (!expanded) {
	    struct loaded_feature_searching fs;
	    fs.name = feature;
	    fs.len = len;
	    fs.type = type;
	    fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
	    fs.result = 0;
	    st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
	    if ((f = fs.result) != 0) {
		if (fn) *fn = f;
		goto loading;
	    }
	}
	if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
	    if (fn) *fn = (const char*)data;
	  loading:
	    if (!ext) return 'u';
	    return !IS_RBEXT(ext) ? 's' : 'r';
	}
	else {
	    VALUE bufstr;
	    char *buf;
	    static const char so_ext[][4] = {
		".so", ".o",
	    };

	    if (ext && *ext) return 0;
	    bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
	    buf = RSTRING_PTR(bufstr);
	    MEMCPY(buf, feature, char, len);
	    for (i = 0; (e = loadable_ext[i]) != 0; i++) {
		strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
		if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
		    rb_str_resize(bufstr, 0);
		    if (fn) *fn = (const char*)data;
		    return i ? 's' : 'r';
		}
	    }
	    for (i = 0; i < numberof(so_ext); i++) {
		strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
		if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
		    rb_str_resize(bufstr, 0);
		    if (fn) *fn = (const char*)data;
		    return 's';
		}
	    }
	    rb_str_resize(bufstr, 0);
	}
    }
    return 0;
}
Beispiel #3
0
mrb_value
mrb_check_intern_str(mrb_state *mrb, mrb_value str)
{
  return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
Beispiel #4
0
VALUE string_spec_RSTRING_LEN(VALUE self, VALUE str) {
  return INT2FIX(RSTRING_LEN(str));
}
Beispiel #5
0
VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) {
  VALUE buf = GET_BUF(self);
  rb_str_buf_cat(buf, RSTRING_PTR(str), RSTRING_LEN(str));
  return Qnil;
}
static grn_table_cursor *
rb_grn_patricia_trie_open_grn_prefix_cursor (int argc, VALUE *argv, VALUE self,
					     grn_ctx **context)
{
    grn_obj *table;
    grn_table_cursor *cursor;
    void *prefix = NULL;
    unsigned prefix_size = 0;
    int offset = 0, limit = -1;
    int flags = GRN_CURSOR_PREFIX;
    VALUE options, rb_prefix, rb_key_bytes, rb_key_bits;
    VALUE rb_order, rb_order_by;
    VALUE rb_greater_than, rb_less_than, rb_offset, rb_limit;

    rb_grn_table_deconstruct((RbGrnTable *)SELF(self), &table, context,
			     NULL, NULL,
			     NULL, NULL, NULL,
			     NULL);

    rb_scan_args(argc, argv, "11", &rb_prefix, &options);

    rb_grn_scan_options(options,
			"key_bytes", &rb_key_bytes,
                        "key_bites", &rb_key_bits,
                        "offset", &rb_offset,
                        "limit", &rb_limit,
			"order", &rb_order,
			"order_by", &rb_order_by,
			"greater_than", &rb_greater_than,
			"less_than", &rb_less_than,
			NULL);

    prefix = StringValuePtr(rb_prefix);
    if (!NIL_P(rb_key_bytes) && !NIL_P(rb_key_bits)) {
	rb_raise(rb_eArgError,
		 "should not specify both :key_bytes and :key_bits once: %s",
		 rb_grn_inspect(rb_ary_new4(argc, argv)));
    } else if (!NIL_P(rb_key_bytes)) {
	prefix_size = NUM2UINT(rb_key_bytes);
    } else if (!NIL_P(rb_key_bits)) {
	prefix_size = NUM2UINT(rb_key_bits);
	flags |= GRN_CURSOR_SIZE_BY_BIT;
    } else {
	prefix_size = RSTRING_LEN(rb_prefix);
    }
    if (!NIL_P(rb_offset))
	offset = NUM2INT(rb_offset);
    if (!NIL_P(rb_limit))
	limit = NUM2INT(rb_limit);

    if (NIL_P(rb_order)) {
    } else if (rb_grn_equal_option(rb_order, "asc") ||
	       rb_grn_equal_option(rb_order, "ascending")) {
	flags |= GRN_CURSOR_ASCENDING;
    } else if (rb_grn_equal_option(rb_order, "desc") ||
	       rb_grn_equal_option(rb_order, "descending")) {
	flags |= GRN_CURSOR_DESCENDING;
    } else {
	rb_raise(rb_eArgError,
		 "order should be one of "
		 "[:asc, :ascending, :desc, :descending]: %s",
		 rb_grn_inspect(rb_order));
    }
    if (NIL_P(rb_order_by)) {
    } else if (rb_grn_equal_option(rb_order_by, "id")) {
	flags |= GRN_CURSOR_BY_ID;
    } else if (rb_grn_equal_option(rb_order_by, "key")) {
	if (table->header.type != GRN_TABLE_PAT_KEY) {
	    rb_raise(rb_eArgError,
		     "order_by => :key is available "
		     "only for Groonga::PatriciaTrie: %s",
		     rb_grn_inspect(self));
	}
	flags |= GRN_CURSOR_BY_KEY;
    } else {
	rb_raise(rb_eArgError,
		 "order_by should be one of [:id%s]: %s",
		 table->header.type == GRN_TABLE_PAT_KEY ? ", :key" : "",
		 rb_grn_inspect(rb_order_by));
    }

    if (RVAL2CBOOL(rb_greater_than))
	flags |= GRN_CURSOR_GT;
    if (RVAL2CBOOL(rb_less_than))
	flags |= GRN_CURSOR_LT;

    cursor = grn_table_cursor_open(*context, table,
				   prefix, prefix_size,
				   NULL, 0,
				   offset, limit, flags);
    rb_grn_context_check(*context, self);

    return cursor;
}
Beispiel #7
0
VALUE string_spec_rb_external_str_new(VALUE self, VALUE str) {
  return rb_external_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
}
Beispiel #8
0
/**
 * RubyWatchman.query(query, socket)
 *
 * Converts `query`, a Watchman query comprising Ruby objects, into the Watchman
 * binary protocol format, transmits it over socket, and unserializes and
 * returns the result.
 */
VALUE RubyWatchman_query(VALUE self, VALUE query, VALUE socket) {
    VALUE error = Qnil;
    VALUE errorClass = Qnil;
    VALUE loaded = Qnil;
    void *buffer = NULL;
    int fileno = NUM2INT(rb_funcall(socket, rb_intern("fileno"), 0));

    // do blocking I/O to simplify the following logic
    int flags = fcntl(fileno, F_GETFL);
    if (
        !(flags & O_NONBLOCK) &&
        fcntl(fileno, F_SETFL, flags & ~O_NONBLOCK) == -1
    ) {
        error = rb_str_new2("unable to clear O_NONBLOCK flag");
        goto cleanup;
    }

    // send the message
    VALUE serialized = RubyWatchman_dump(self, query);
    long query_len = RSTRING_LEN(serialized);
    ssize_t sent = send(fileno, RSTRING_PTR(serialized), query_len, 0);
    if (sent == -1) {
        goto system_call_fail;
    } else if (sent != query_len) {
        error = rb_str_new2("sent byte count mismatch");
        goto cleanup;
    }

    // sniff to see how large the header is
    int8_t peek[WATCHMAN_PEEK_BUFFER_SIZE];
    ssize_t received =
        recv(fileno, peek, WATCHMAN_SNIFF_BUFFER_SIZE, MSG_PEEK | MSG_WAITALL);
    if (received == -1) {
        goto system_call_fail;
    } else if (received != WATCHMAN_SNIFF_BUFFER_SIZE) {
        error = rb_str_new2("failed to sniff PDU header");
        goto cleanup;
    }

    // peek at size of PDU
    int8_t sizes[] = { 0, 0, 0, 1, 2, 4, 8 };
    int8_t sizes_idx = peek[sizeof(WATCHMAN_BINARY_MARKER) - 1];
    if (sizes_idx < WATCHMAN_INT8_MARKER || sizes_idx > WATCHMAN_INT64_MARKER) {
        error = rb_str_new2("bad PDU size marker");
        goto cleanup;
    }
    ssize_t peek_size = sizeof(WATCHMAN_BINARY_MARKER) - 1 + sizeof(int8_t) +
        sizes[sizes_idx];

    received = recv(fileno, peek, peek_size, MSG_PEEK);
    if (received == -1) {
        goto system_call_fail;
    } else if (received != peek_size) {
        error = rb_str_new2("failed to peek at PDU header");
        goto cleanup;
    }
    int8_t *pdu_size_ptr =
        peek + sizeof(WATCHMAN_BINARY_MARKER) - sizeof(int8_t);
    int64_t payload_size =
        peek_size +
        watchman_load_int((char **)&pdu_size_ptr, (char *)peek + peek_size);

    // actually read the PDU
    buffer = xmalloc(payload_size);
    if (!buffer) {
        errorClass = rb_eNoMemError;
        error = rb_str_new2("failed to allocate");
        goto cleanup;
    }
    received = recv(fileno, buffer, payload_size, MSG_WAITALL);
    if (received == -1) {
        goto system_call_fail;
    } else if (received != payload_size) {
        error = rb_str_new2("failed to load PDU");
        goto cleanup;
    }

    if (!(flags & O_NONBLOCK) && fcntl(fileno, F_SETFL, flags) == -1) {
        error = rb_str_new2("unable to restore fnctl flags");
        goto cleanup;
    }

    char *payload = buffer + peek_size;
    loaded = watchman_load(&payload, payload + payload_size);
    goto cleanup;

system_call_fail:
    errorClass = rb_eSystemCallError;
    error = INT2FIX(errno);

cleanup:
    if (buffer) {
        xfree(buffer);
    }

    if (!(flags & O_NONBLOCK) && fcntl(fileno, F_SETFL, flags) == -1) {
        rb_raise(rb_eRuntimeError, "unable to restore fnctl flags");
    }

    if (NIL_P(errorClass)) {
        errorClass = rb_eRuntimeError;
    }

    if (!NIL_P(error)) {
        rb_exc_raise(rb_class_new_instance(1, &error, errorClass));
    }

    return loaded;
}
Beispiel #9
0
// based on https://gist.github.com/3066997
static mrb_value
migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) {
  mrb_value nv = mrb_nil_value();

  nv.tt = v.tt;
  switch (mrb_type(v)) {
  case MRB_TT_OBJECT:
    nv.value.p = v.value.p;
    break;
  case MRB_TT_FALSE:
  case MRB_TT_TRUE:
  case MRB_TT_FIXNUM:
    nv.value.i = v.value.i;
    break;
  case MRB_TT_SYMBOL:
    nv = mrb_symbol_value(mrb_intern_str(mrb2, v));
    break;
  case MRB_TT_FLOAT:
    nv.value.f = v.value.f;
    break;
  case MRB_TT_STRING:
    nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v));
    break;
  case MRB_TT_ARRAY:
    {
      struct RArray *a0, *a1;
      int i;

      a0 = mrb_ary_ptr(v);
      nv = mrb_ary_new_capa(mrb2, a0->len);
      a1 = mrb_ary_ptr(nv);
      for (i=0; i<a0->len; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2);
        a1->len++;
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    break;
  case MRB_TT_HASH:
    {
      mrb_value ka;
      int i, l;

      nv = mrb_hash_new(mrb2);
      ka = mrb_hash_keys(mrb, v);
      l = RARRAY_LEN(ka);
      for (i = 0; i < l; i++) {
        int ai = mrb_gc_arena_save(mrb2);
        mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2);
        mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2);
        mrb_hash_set(mrb2, nv, k, o);
        mrb_gc_arena_restore(mrb2, ai);
      }
    }
    break;
  default:
    mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object");
    break;
  }
  return nv;
}
Beispiel #10
0
static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
  int ai;
  mrb_code *pc, *pcend;
  mrb_code ins;
  const char *file = NULL, *next_file;

  if (!irep) return;
  printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d iseq=%d\n", (void*)irep,
         irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen, (int)irep->ilen);

  if (irep->lv) {
    int i;

    printf("local variable names:\n");
    for (i = 1; i < irep->nlocals; ++i) {
      char const *s = mrb_sym2name(mrb, irep->lv[i - 1].name);
      int n = irep->lv[i - 1].r ? irep->lv[i - 1].r : i;
      printf("  R%d:%s\n", n, s ? s : "");
    }
  }

  pc = irep->iseq;
  pcend = pc + irep->ilen;
  while (pc < pcend) {
    ptrdiff_t i;
    uint32_t a;
    uint16_t b;
    uint8_t c;

    ai = mrb_gc_arena_save(mrb);

    i = pc - irep->iseq;
    next_file = mrb_debug_get_filename(mrb, irep, i);
    if (next_file && file != next_file) {
      printf("file: %s\n", next_file);
      file = next_file;
    }
    print_header(mrb, irep, i);
    ins = READ_B();
    switch (ins) {
    CASE(OP_NOP, Z):
      printf("OP_NOP\n");
      break;
    CASE(OP_MOVE, BB):
      printf("OP_MOVE\tR%d\tR%d\t", a, b);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_LOADL, BB):
      {
        mrb_value v = irep->pool[b];
        mrb_value s = mrb_inspect(mrb, v);
        printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
      }
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI, BB):
      printf("OP_LOADI\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADINEG, BB):
      printf("OP_LOADI\tR%d\t-%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI__1, B):
      printf("OP_LOADI__1\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADI_0, B): goto L_LOADI;
    CASE(OP_LOADI_1, B): goto L_LOADI;
    CASE(OP_LOADI_2, B): goto L_LOADI;
    CASE(OP_LOADI_3, B): goto L_LOADI;
    CASE(OP_LOADI_4, B): goto L_LOADI;
    CASE(OP_LOADI_5, B): goto L_LOADI;
    CASE(OP_LOADI_6, B): goto L_LOADI;
    CASE(OP_LOADI_7, B):
    L_LOADI:
      printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADSYM, BB):
      printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADNIL, B):
      printf("OP_LOADNIL\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADSELF, B):
      printf("OP_LOADSELF\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADT, B):
      printf("OP_LOADT\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LOADF, B):
      printf("OP_LOADF\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETGV, BB):
      printf("OP_GETGV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETGV, BB):
      printf("OP_SETGV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETSV, BB):
      printf("OP_GETSV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETSV, BB):
      printf("OP_SETSV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETCONST, BB):
      printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETCONST, BB):
      printf("OP_SETCONST\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETMCNST, BB):
      printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETMCNST, BB):
      printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETIV, BB):
      printf("OP_GETIV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETIV, BB):
      printf("OP_SETIV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETUPVAR, BBB):
      printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETUPVAR, BBB):
      printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_GETCV, BB):
      printf("OP_GETCV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SETCV, BB):
      printf("OP_SETCV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMP, S):
      printf("OP_JMP\t\t%03d\n", a);
      break;
    CASE(OP_JMPIF, BS):
      printf("OP_JMPIF\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMPNOT, BS):
      printf("OP_JMPNOT\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_JMPNIL, BS):
      printf("OP_JMPNIL\tR%d\t%03d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SENDV, BB):
      printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_SENDVB, BB):
      printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_SEND, BBB):
      printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
      break;
    CASE(OP_SENDB, BBB):
      printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c);
      break;
    CASE(OP_CALL, Z):
      printf("OP_CALL\n");
      break;
    CASE(OP_SUPER, BB):
      printf("OP_SUPER\tR%d\t%d\n", a, b);
      break;
    CASE(OP_ARGARY, BS):
      printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a,
             (b>>11)&0x3f,
             (b>>10)&0x1,
             (b>>5)&0x1f,
             (b>>4)&0x1,
             (b>>0)&0xf);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ENTER, W):
      printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
             (a>>18)&0x1f,
             (a>>13)&0x1f,
             (a>>12)&0x1,
             (a>>7)&0x1f,
             (a>>2)&0x1f,
             (a>>1)&0x1,
             a & 0x1);
      break;
    CASE(OP_KEY_P, BB):
      printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_KEYEND, Z):
      printf("OP_KEYEND\n");
      break;
    CASE(OP_KARG, BB):
      printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RETURN, B):
      printf("OP_RETURN\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RETURN_BLK, B):
      printf("OP_RETURN_BLK\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_BREAK, B):
      printf("OP_BREAK\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_BLKPUSH, BS):
      printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a,
             (b>>11)&0x3f,
             (b>>10)&0x1,
             (b>>5)&0x1f,
             (b>>4)&0x1,
             (b>>0)&0xf);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_LAMBDA, BB):
      printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_BLOCK, BB):
      printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_METHOD, BB):
      printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]);
      break;
    CASE(OP_RANGE_INC, B):
      printf("OP_RANGE_INC\tR%d\n", a);
      break;
    CASE(OP_RANGE_EXC, B):
      printf("OP_RANGE_EXC\tR%d\n", a);
      break;
    CASE(OP_DEF, BB):
      printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_UNDEF, B):
      printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a]));
      break;
    CASE(OP_ALIAS, BB):
      printf("OP_ALIAS\t:%s\t%s\n", mrb_sym2name(mrb, irep->syms[a]), mrb_sym2name(mrb, irep->syms[b]));
      break;
    CASE(OP_ADD, B):
      printf("OP_ADD\tR%d\t\n", a);
      break;
    CASE(OP_ADDI, BB):
      printf("OP_ADDI\tR%d\t%d\n", a, b);
      break;
    CASE(OP_SUB, B):
      printf("OP_SUB\tR%d\t\n", a);
      break;
    CASE(OP_SUBI, BB):
      printf("OP_SUBI\tR%d\t%d\n", a, b);
      break;
    CASE(OP_MUL, B):
      printf("OP_MUL\tR%d\t\n", a);
      break;
    CASE(OP_DIV, B):
      printf("OP_DIV\tR%d\t\n", a);
      break;
    CASE(OP_LT, B):
      printf("OP_LT\t\tR%d\t\n", a);
      break;
    CASE(OP_LE, B):
      printf("OP_LE\t\tR%d\t\n", a);
      break;
    CASE(OP_GT, B):
      printf("OP_GT\t\tR%d\t\n", a);
      break;
    CASE(OP_GE, B):
      printf("OP_GE\t\tR%d\t\n", a);
      break;
    CASE(OP_EQ, B):
      printf("OP_EQ\t\tR%d\t\n", a);
      break;
    CASE(OP_ARRAY, BB):
      printf("OP_ARRAY\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARRAY2, BBB):
      printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_ARYCAT, B):
      printf("OP_ARYCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARYPUSH, B):
      printf("OP_ARYPUSH\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ARYDUP, B):
      printf("OP_ARYDUP\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_AREF, BBB):
      printf("OP_AREF\tR%d\tR%d\t%d", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_ASET, BBB):
      printf("OP_ASET\tR%d\tR%d\t%d", a, b, c);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_APOST, BBB):
      printf("OP_APOST\tR%d\t%d\t%d", a, b, c);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_INTERN, B):
      printf("OP_INTERN\tR%d", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_STRING, BB):
      {
        mrb_value v = irep->pool[b];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s));
      }
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_STRCAT, B):
      printf("OP_STRCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASH, BB):
      printf("OP_HASH\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASHADD, BB):
      printf("OP_HASHADD\tR%d\t%d\t", a, b);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_HASHCAT, B):
      printf("OP_HASHCAT\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;

    CASE(OP_OCLASS, B):
      printf("OP_OCLASS\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_CLASS, BB):
      printf("OP_CLASS\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_MODULE, BB):
      printf("OP_MODULE\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b]));
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_EXEC, BB):
      printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_SCLASS, B):
      printf("OP_SCLASS\tR%d\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_TCLASS, B):
      printf("OP_TCLASS\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_ERR, B):
      {
        mrb_value v = irep->pool[a];
        mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
        printf("OP_ERR\t%s\n", RSTRING_PTR(s));
      }
      break;
    CASE(OP_EPUSH, B):
      printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]);
      break;
    CASE(OP_ONERR, S):
      printf("OP_ONERR\t%03d\n", a);
      break;
    CASE(OP_EXCEPT, B):
      printf("OP_EXCEPT\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_RESCUE, BB):
      printf("OP_RESCUE\tR%d\tR%d", a, b);
      print_lv_ab(mrb, irep, a, b);
      break;
    CASE(OP_RAISE, B):
      printf("OP_RAISE\tR%d\t\t", a);
      print_lv_a(mrb, irep, a);
      break;
    CASE(OP_POPERR, B):
      printf("OP_POPERR\t%d\t\t\n", a);
      break;
    CASE(OP_EPOP, B):
      printf("OP_EPOP\t%d\n", a);
      break;

    CASE(OP_DEBUG, BBB):
      printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c);
      break;

    CASE(OP_STOP, Z):
      printf("OP_STOP\n");
      break;

    CASE(OP_EXT1, Z):
      ins = READ_B();
      printf("OP_EXT1\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;
    CASE(OP_EXT2, Z):
      ins = READ_B();
      printf("OP_EXT2\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;
    CASE(OP_EXT3, Z):
      ins = READ_B();
      printf("OP_EXT3\n");
      print_header(mrb, irep, pc-irep->iseq-2);
      switch (ins) {
#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
#include "mruby/ops.h"
#undef OPCODE
      }
      break;

    default:
      printf("OP_unknown (0x%x)\n", ins);
      break;
    }
    mrb_gc_arena_restore(mrb, ai);
  }
  printf("\n");
}
Beispiel #11
0
/**
 * Encodes and appends the string `string` to `w`
 */
void watchman_dump_string(watchman_t *w, VALUE string) {
    watchman_append(w, &watchman_string_marker, sizeof(watchman_string_marker));
    watchman_dump_int(w, RSTRING_LEN(string));
    watchman_append(w, RSTRING_PTR(string), RSTRING_LEN(string));
}
Beispiel #12
0
static void
error_print(void)
{
    volatile VALUE errat = Qnil;		/* OK */
    rb_thread_t *th = GET_THREAD();
    VALUE errinfo = th->errinfo;
    int raised_flag = th->raised_flag;
    volatile VALUE eclass, e;
    const char *volatile einfo;
    volatile long elen;

    if (NIL_P(errinfo))
	return;
    rb_thread_raised_clear(th);

    PUSH_TAG();
    if (EXEC_TAG() == 0) {
	errat = get_backtrace(errinfo);
    }
    else {
	errat = Qnil;
    }
    if (EXEC_TAG())
	goto error;
    if (NIL_P(errat)) {
	const char *file = rb_sourcefile();
	int line = rb_sourceline();
	if (!file)
	    warn_printf("%d", line);
	else if (!line)
	    warn_printf("%s", file);
	else
	    warn_printf("%s:%d", file, line);
    }
    else if (RARRAY_LEN(errat) == 0) {
	error_pos();
    }
    else {
	VALUE mesg = RARRAY_PTR(errat)[0];

	if (NIL_P(mesg))
	    error_pos();
	else {
	    warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
	}
    }

    eclass = CLASS_OF(errinfo);
    if (EXEC_TAG() == 0) {
	e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
	StringValue(e);
	einfo = RSTRING_PTR(e);
	elen = RSTRING_LEN(e);
    }
    else {
	einfo = "";
	elen = 0;
    }
    if (EXEC_TAG())
	goto error;
    if (eclass == rb_eRuntimeError && elen == 0) {
	warn_print(": unhandled exception\n");
    }
    else {
	VALUE epath;

	epath = rb_class_name(eclass);
	if (elen == 0) {
	    warn_print(": ");
	    warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
	    warn_print("\n");
	}
	else {
	    char *tail = 0;
	    long len = elen;

	    if (RSTRING_PTR(epath)[0] == '#')
		epath = 0;
	    if ((tail = memchr(einfo, '\n', elen)) != 0) {
		len = tail - einfo;
		tail++;		/* skip newline */
	    }
	    warn_print(": ");
	    warn_print2(einfo, len);
	    if (epath) {
		warn_print(" (");
		warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
		warn_print(")\n");
	    }
	    if (tail) {
		warn_print2(tail, elen - len - 1);
		if (einfo[elen-1] != '\n') warn_print2("\n", 1);
	    }
	}
    }

    if (!NIL_P(errat)) {
	long i;
	long len = RARRAY_LEN(errat);
	VALUE *ptr = RARRAY_PTR(errat);
        int skip = eclass == rb_eSysStackError;

#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
#define TRACE_HEAD 8
#define TRACE_TAIL 5

	for (i = 1; i < len; i++) {
	    if (RB_TYPE_P(ptr[i], T_STRING)) {
		warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
	    }
	    if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
		warn_printf("\t ... %ld levels...\n",
			    len - TRACE_HEAD - TRACE_TAIL);
		i = len - TRACE_TAIL;
	    }
	}
    }
  error:
    POP_TAG();
    rb_thread_raised_set(th, raised_flag);
}
/*
 * call-seq:
 *    ctx.setup => Qtrue # first time
 *    ctx.setup => nil # thereafter
 *
 * This method is called automatically when a new SSLSocket is created.
 * Normally you do not need to call this method (unless you are writing an extension in C).
 */
static VALUE
ossl_sslctx_setup(VALUE self)
{
    SSL_CTX *ctx;
    X509 *cert = NULL, *client_ca = NULL;
    X509_STORE *store;
    EVP_PKEY *key = NULL;
    char *ca_path = NULL, *ca_file = NULL;
    int i, verify_mode;
    VALUE val;

    if(OBJ_FROZEN(self)) return Qnil;
    Data_Get_Struct(self, SSL_CTX, ctx);

#if !defined(OPENSSL_NO_DH)
    if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
	SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
    }
    else{
	SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
    }
#endif
    SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);

    val = ossl_sslctx_get_cert_store(self);
    if(!NIL_P(val)){
	/*
         * WORKAROUND:
	 *   X509_STORE can count references, but
	 *   X509_STORE_free() doesn't care it.
	 *   So we won't increment it but mark it by ex_data.
	 */
        store = GetX509StorePtr(val); /* NO NEED TO DUP */
        SSL_CTX_set_cert_store(ctx, store);
        SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
    }

    val = ossl_sslctx_get_extra_cert(self);
    if(!NIL_P(val)){
	rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
    }

    /* private key may be bundled in certificate file. */
    val = ossl_sslctx_get_cert(self);
    cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
    val = ossl_sslctx_get_key(self);
    key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
    if (cert && key) {
        if (!SSL_CTX_use_certificate(ctx, cert)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_certificate:");
        }
        if (!SSL_CTX_use_PrivateKey(ctx, key)) {
            /* Adds a ref => Safe to FREE */
            ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:");
        }
        if (!SSL_CTX_check_private_key(ctx)) {
            ossl_raise(eSSLError, "SSL_CTX_check_private_key:");
        }
    }

    val = ossl_sslctx_get_client_ca(self);
    if(!NIL_P(val)){
	if(TYPE(val) == T_ARRAY){
	    for(i = 0; i < RARRAY_LEN(val); i++){
		client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
        	if (!SSL_CTX_add_client_CA(ctx, client_ca)){
		    /* Copies X509_NAME => FREE it. */
        	    ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
        	}
	    }
        }
	else{
	    client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
            if (!SSL_CTX_add_client_CA(ctx, client_ca)){
		/* Copies X509_NAME => FREE it. */
        	ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
            }
	}
    }

    val = ossl_sslctx_get_ca_file(self);
    ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
    val = ossl_sslctx_get_ca_path(self);
    ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
    if(ca_file || ca_path){
	if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
	    rb_warning("can't set verify locations");
    }

    val = ossl_sslctx_get_verify_mode(self);
    verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
    SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
    if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
	SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);

    val = ossl_sslctx_get_timeout(self);
    if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));

    val = ossl_sslctx_get_verify_dep(self);
    if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val));

    val = ossl_sslctx_get_options(self);
    if(!NIL_P(val)) {
    	SSL_CTX_set_options(ctx, NUM2LONG(val));
    } else {
	SSL_CTX_set_options(ctx, SSL_OP_ALL);
    }
    rb_obj_freeze(self);

    val = ossl_sslctx_get_sess_id_ctx(self);
    if (!NIL_P(val)){
	StringValue(val);
	if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
					    RSTRING_LEN(val))){
	    ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
	}
    }

    if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
	SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
	OSSL_Debug("SSL SESSION get callback added");
    }
    if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
	SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
	OSSL_Debug("SSL SESSION new callback added");
    }
    if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
	SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
	OSSL_Debug("SSL SESSION remove callback added");
    }
    return Qtrue;
}
Beispiel #14
0
static VALUE
string_to_c_internal(VALUE self)
{
    VALUE s;

    s = self;

    if (RSTRING_LEN(s) == 0)
	return rb_assoc_new(Qnil, self);

    {
	VALUE m, sr, si, re, r, i;
	int po;

	m = f_match(comp_pat0, s);
	if (!NIL_P(m)) {
	  sr = f_aref(m, INT2FIX(1));
	  si = f_aref(m, INT2FIX(2));
	  re = f_post_match(m);
	  po = 1;
	}
	if (NIL_P(m)) {
	    m = f_match(comp_pat1, s);
	    if (!NIL_P(m)) {
		sr = Qnil;
		si = f_aref(m, INT2FIX(1));
		if (NIL_P(si))
		    si = rb_usascii_str_new2("");
		{
		    VALUE t;

		    t = f_aref(m, INT2FIX(2));
		    if (NIL_P(t))
			t = rb_usascii_str_new2("1");
		    rb_str_concat(si, t);
		}
		re = f_post_match(m);
		po = 0;
	    }
	}
	if (NIL_P(m)) {
	    m = f_match(comp_pat2, s);
	    if (NIL_P(m))
		return rb_assoc_new(Qnil, self);
	    sr = f_aref(m, INT2FIX(1));
	    if (NIL_P(f_aref(m, INT2FIX(2))))
		si = Qnil;
	    else {
		VALUE t;

		si = f_aref(m, INT2FIX(3));
		t = f_aref(m, INT2FIX(4));
		if (NIL_P(t))
		    t = rb_usascii_str_new2("1");
		rb_str_concat(si, t);
	    }
	    re = f_post_match(m);
	    po = 0;
	}
	r = INT2FIX(0);
	i = INT2FIX(0);
	if (!NIL_P(sr)) {
	    if (f_include_p(sr, a_slash))
		r = f_to_r(sr);
	    else if (f_gt_p(f_count(sr, a_dot_and_an_e), INT2FIX(0)))
		r = f_to_f(sr);
	    else
		r = f_to_i(sr);
	}
	if (!NIL_P(si)) {
	    if (f_include_p(si, a_slash))
		i = f_to_r(si);
	    else if (f_gt_p(f_count(si, a_dot_and_an_e), INT2FIX(0)))
		i = f_to_f(si);
	    else
		i = f_to_i(si);
	}
	if (po)
	    return rb_assoc_new(rb_complex_polar(r, i), re);
	else
	    return rb_assoc_new(rb_complex_new2(r, i), re);
    }
}
static int
rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
{
    VALUE v, features, p, load_path = 0;
    const char *f, *e;
    long i, len, elen, n;
    st_table *loading_tbl;
    st_data_t data;
    int type;

    if (fn) *fn = 0;
    if (ext) {
	elen = strlen(ext);
	len = strlen(feature) - elen;
	type = rb ? 'r' : 's';
    }
    else {
	len = strlen(feature);
	elen = 0;
	type = 0;
    }
    features = get_loaded_features();
    for (i = 0; i < RARRAY_LEN(features); ++i) {
	v = RARRAY_PTR(features)[i];
	f = StringValuePtr(v);
	if ((n = RSTRING_LEN(v)) < len) continue;
	if (strncmp(f, feature, len) != 0) {
	    if (expanded) continue;
	    if (!load_path) load_path = rb_get_expanded_load_path();
	    if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
		continue;
	    expanded = 1;
	    f += RSTRING_LEN(p) + 1;
	}
	if (!*(e = f + len)) {
	    if (ext) continue;
	    return 'u';
	}
	if (*e != '.') continue;
	if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
	    return 's';
	}
	if ((rb || !ext) && (IS_RBEXT(e))) {
	    return 'r';
	}
    }
    loading_tbl = get_loading_table();
    if (loading_tbl) {
	f = 0;
	if (!expanded) {
	    struct loaded_feature_searching fs;
	    fs.name = feature;
	    fs.len = len;
	    fs.type = type;
	    fs.load_path = load_path ? load_path : rb_get_load_path();
	    fs.result = 0;
	    st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
	    if ((f = fs.result) != 0) {
		if (fn) *fn = f;
		goto loading;
	    }
	}
	if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
	    if (fn) *fn = (const char*)data;
	  loading:
	    if (!ext) return 'u';
	    return !IS_RBEXT(ext) ? 's' : 'r';
	}
	else {
	    VALUE bufstr;
	    char *buf;

	    if (ext && *ext) return 0;
	    bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
	    buf = RSTRING_PTR(bufstr);
	    MEMCPY(buf, feature, char, len);
	    for (i = 0; (e = loadable_ext[i]) != 0; i++) {
		strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
		if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
		    rb_str_resize(bufstr, 0);
		    if (fn) *fn = (const char*)data;
		    return i ? 's' : 'r';
		}
	    }
	    rb_str_resize(bufstr, 0);
	}
    }
    return 0;
}
Beispiel #16
0
static mrb_value http_request_method(mrb_state *mrb, mrb_value self)
{
    h2o_mruby_generator_t *generator;
    struct st_h2o_mruby_http_request_context_t *ctx;
    const char *arg_url;
    mrb_int arg_url_len;
    mrb_value arg_hash;
    h2o_iovec_t method;
    h2o_url_t url;

    /* parse args */
    arg_hash = mrb_nil_value();
    mrb_get_args(mrb, "s|H", &arg_url, &arg_url_len, &arg_hash);

    /* precond check */
    if ((generator = h2o_mruby_current_generator) == NULL || generator->req == NULL)
        mrb_exc_raise(mrb, create_downstream_closed_exception(mrb));

    /* allocate context and initialize */
    ctx = h2o_mem_alloc_shared(&generator->req->pool, sizeof(*ctx), on_dispose);
    memset(ctx, 0, sizeof(*ctx));
    ctx->generator = generator;
    ctx->receiver = mrb_nil_value();
    h2o_buffer_init(&ctx->req.buf, &h2o_socket_buffer_prototype);
    h2o_buffer_init(&ctx->resp.after_closed, &h2o_socket_buffer_prototype);
    ctx->refs.request = mrb_nil_value();
    ctx->refs.input_stream = mrb_nil_value();

    /* uri */
    if (h2o_url_parse(arg_url, arg_url_len, &url) != 0)
        mrb_raise(mrb, E_ARGUMENT_ERROR, "invaild URL");

    /* method */
    method = h2o_iovec_init(H2O_STRLIT("GET"));
    if (mrb_hash_p(arg_hash)) {
        mrb_value t = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_method));
        if (!mrb_nil_p(t)) {
            t = mrb_str_to_str(mrb, t);
            method = h2o_iovec_init(RSTRING_PTR(t), RSTRING_LEN(t));
        }
    }

    /* start building the request */
    h2o_buffer_reserve(&ctx->req.buf, method.len + 1);
    append_to_buffer(&ctx->req.buf, method.base, method.len);
    append_to_buffer(&ctx->req.buf, H2O_STRLIT(" "));
    h2o_buffer_reserve(&ctx->req.buf,
                       url.path.len + url.authority.len + sizeof(" HTTP/1.1\r\nConnection: close\r\nHost: \r\n") - 1);
    append_to_buffer(&ctx->req.buf, url.path.base, url.path.len);
    append_to_buffer(&ctx->req.buf, H2O_STRLIT(" HTTP/1.1\r\nConnection: close\r\nHost: "));
    append_to_buffer(&ctx->req.buf, url.authority.base, url.authority.len);
    append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n"));

    /* headers */
    if (mrb_hash_p(arg_hash)) {
        mrb_value headers = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_headers));
        if (!mrb_nil_p(headers)) {
            if (h2o_mruby_iterate_headers(generator->ctx, headers, flatten_request_header, ctx) != 0) {
                mrb_value exc = mrb_obj_value(mrb->exc);
                mrb->exc = NULL;
                mrb_exc_raise(mrb, exc);
            }
        }
    }
    /* body */
    if (mrb_hash_p(arg_hash)) {
        mrb_value body = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_body));
        if (!mrb_nil_p(body)) {
            if (mrb_obj_eq(mrb, body, generator->rack_input)) {
                /* fast path */
                mrb_int pos;
                mrb_input_stream_get_data(mrb, body, NULL, NULL, &pos, NULL, NULL);
                ctx->req.body = generator->req->entity;
                ctx->req.body.base += pos;
                ctx->req.body.len -= pos;
            } else {
                if (!mrb_string_p(body)) {
                    body = mrb_funcall(mrb, body, "read", 0);
                    if (!mrb_string_p(body))
                        mrb_raise(mrb, E_ARGUMENT_ERROR, "body.read did not return string");
                }
                ctx->req.body = h2o_strdup(&ctx->generator->req->pool, RSTRING_PTR(body), RSTRING_LEN(body));
            }
            if (!ctx->req.has_transfer_encoding) {
                char buf[64];
                size_t l = (size_t)sprintf(buf, "content-length: %zu\r\n", ctx->req.body.len);
                h2o_buffer_reserve(&ctx->req.buf, l);
                append_to_buffer(&ctx->req.buf, buf, l);
            }
        }
    }

    h2o_buffer_reserve(&ctx->req.buf, 2);
    append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n"));

    /* build request and connect */
    h2o_http1client_connect(&ctx->client, ctx, &generator->req->conn->ctx->proxy.client_ctx, url.host, h2o_url_get_port(&url),
                            url.scheme == &H2O_URL_SCHEME_HTTPS, on_connect);

    ctx->refs.request = h2o_mruby_create_data_instance(
        mrb, mrb_ary_entry(generator->ctx->shared->constants, H2O_MRUBY_HTTP_REQUEST_CLASS), ctx, &request_type);
    return ctx->refs.request;
}
/*
 * call-seq:
 *   Groonga::PatriciaTrie.create(options={}) -> Groonga::PatriciaTrie
 *   Groonga::PatriciaTrie.create(options={}) {|table| ... }
 *
 * 各レコードをパトリシアトライで管理するテーブルを生成する。
 * ブロックを指定すると、そのブロックに生成したテーブルが渡さ
 * れ、ブロックを抜けると自動的にテーブルが破棄される。
 *
 * _options_に指定可能な値は以下の通り。
 *
 * [+:context+]
 *   テーブルが利用するGroonga::Context。省略すると
 *   Groonga::Context.defaultを用いる。
 *
 * [+:name+]
 *   テーブルの名前。名前をつけると、Groonga::Context#[]に名
 *   前を指定してテーブルを取得することができる。省略すると
 *   無名テーブルになり、テーブルIDでのみ取得できる。
 *
 * [+:path+]
 *   テーブルを保存するパス。パスを指定すると永続テーブルとな
 *   り、プロセス終了後もレコードは保持される。次回起動時に
 *   Groonga::Context#[]で保存されたレコードを利用する
 *   ことができる。省略すると一時テーブルになり、プロセスが終
 *   了するとレコードは破棄される。
 *
 * [+:persistent+]
 *   +true+を指定すると永続テーブルとなる。+path+を省略した
 *   場合は自動的にパスが付加される。+:context+で指定した
 *   Groonga::Contextに結びついているデータベースが一時デー
 *   タベースの場合は例外が発生する。
 *
 * [+:key_normalize+]
 *   +true+を指定するとキーを正規化する。
 *
 * [+:key_with_sis+]
 *   +true+を指定するとキーの文字列の全suffixが自動的に登
 *   録される。
 *
 * [+:key_type+]
 *   キーの種類を示すオブジェクトを指定する。キーの種類には型
 *   名("Int32"や"ShortText"など)またはGroonga::Typeまたは
 *   テーブル(Groonga::Array、Groonga::Hash、
 *   Groonga::PatriciaTrieのどれか)を指定する。
 *
 *   Groonga::Typeを指定した場合は、その型が示す範囲の値をキー
 *   として使用する。ただし、キーの最大サイズは4096バイトで
 *   あるため、Groonga::Type::TEXTやGroonga::Type::LONG_TEXT
 *   は使用できない。
 *
 *   テーブルを指定した場合はレコードIDをキーとして使用する。
 *   指定したテーブルのGroonga::Recordをキーとして使用するこ
 *   ともでき、その場合は自動的にGroonga::Recordからレコード
 *   IDを取得する。
 *
 *   省略した場合はShortText型をキーとして使用する。この場合、
 *   4096バイトまで使用可能である。
 *
 * [+:value_type+]
 *   値の型を指定する。省略すると値のための領域を確保しない。
 *   値を保存したい場合は必ず指定すること。
 *
 *   参考: Groonga::Type.new
 *
 * [+:default_tokenizer+]
 *   Groonga::IndexColumnで使用するトークナイザを指定する。
 *   デフォルトでは何も設定されていないので、テーブルに
 *   Groonga::IndexColumnを定義する場合は
 *   <tt>"TokenBigram"</tt>などを指定する必要がある。
 *
 * [+:sub_records+]
 *   +true+を指定すると#groupでグループ化したときに、
 *   Groonga::Record#n_sub_recordsでグループに含まれるレコー
 *   ドの件数を取得できる。
 *
 * 使用例:
 *
 * 無名一時テーブルを生成する。
 *   Groonga::PatriciaTrie.create
 *
 * 無名永続テーブルを生成する。
 *   Groonga::PatriciaTrie.create(:path => "/tmp/hash.grn")
 *
 * 名前付き永続テーブルを生成する。ただし、ファイル名は気に
 * しない。
 *   Groonga::PatriciaTrie.create(:name => "Bookmarks",
 *                                :persistent => true)
 *
 * それぞれのレコードに512バイトの値を格納できる無名一時テー
 * ブルを生成する。
 *   Groonga::PatriciaTrie.create(:value => 512)
 *
 * キーとして文字列を使用する無名一時テーブルを生成する。
 *   Groonga::PatriciaTrie.create(:key_type => Groonga::Type::SHORT_TEXT)
 *
 * キーとして文字列を使用する無名一時テーブルを生成する。
 * (キーの種類を表すオブジェクトは文字列で指定。)
 *   Groonga::PatriciaTrie.create(:key_type => "ShortText")
 *
 * キーとして<tt>Bookmarks</tt>テーブルのレコードを使用す
 * る無名一時テーブルを生成する。
 *   bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks")
 *   Groonga::PatriciaTrie.create(:key_type => bookmarks)
 *
 * キーとして<tt>Bookmarks</tt>テーブルのレコードを使用す
 * る無名一時テーブルを生成する。
 * (テーブルは文字列で指定。)
 *   Groonga::PatriciaTrie.create(:name => "Bookmarks")
 *   Groonga::PatriciaTrie.create(:key_type => "Bookmarks")
 *
 * 全文検索用のトークンをバイグラムで切り出す無名一時テーブ
 * ルを生成する。
 *   bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks")
 *   bookmarks.define_column("comment", "Text")
 *   terms = Groonga::PatriciaTrie.create(:name => "Terms",
 *                                        :default_tokenizer => "TokenBigram")
 *   terms.define_index_column("content", bookmarks,
 *                             :source => "Bookmarks.comment")
 */
static VALUE
rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
{
    grn_ctx *context;
    grn_obj *key_type = NULL, *value_type = NULL, *table;
    const char *name = NULL, *path = NULL;
    unsigned name_size = 0;
    grn_obj_flags flags = GRN_OBJ_TABLE_PAT_KEY;
    VALUE rb_table;
    VALUE options, rb_context, rb_name, rb_path, rb_persistent;
    VALUE rb_key_normalize, rb_key_with_sis, rb_key_type;
    VALUE rb_value_type;
    VALUE rb_default_tokenizer, rb_sub_records;

    rb_scan_args(argc, argv, "01", &options);

    rb_grn_scan_options(options,
			"context", &rb_context,
			"name", &rb_name,
                        "path", &rb_path,
			"persistent", &rb_persistent,
			"key_normalize", &rb_key_normalize,
			"key_with_sis", &rb_key_with_sis,
			"key_type", &rb_key_type,
			"value_type", &rb_value_type,
			"default_tokenizer", &rb_default_tokenizer,
			"sub_records", &rb_sub_records,
			NULL);

    context = rb_grn_context_ensure(&rb_context);

    if (!NIL_P(rb_name)) {
        name = StringValuePtr(rb_name);
	name_size = RSTRING_LEN(rb_name);
	flags |= GRN_OBJ_PERSISTENT;
    }

    if (!NIL_P(rb_path)) {
        path = StringValueCStr(rb_path);
	flags |= GRN_OBJ_PERSISTENT;
    }

    if (RVAL2CBOOL(rb_persistent))
	flags |= GRN_OBJ_PERSISTENT;

    if (RVAL2CBOOL(rb_key_normalize))
	flags |= GRN_OBJ_KEY_NORMALIZE;

    if (RVAL2CBOOL(rb_key_with_sis))
	flags |= GRN_OBJ_KEY_WITH_SIS;

    if (NIL_P(rb_key_type)) {
	key_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT);
    } else {
	key_type = RVAL2GRNOBJECT(rb_key_type, &context);
    }

    if (!NIL_P(rb_value_type))
	value_type = RVAL2GRNOBJECT(rb_value_type, &context);

    if (RVAL2CBOOL(rb_sub_records))
	flags |= GRN_OBJ_WITH_SUBREC;

    table = grn_table_create(context, name, name_size, path,
			     flags, key_type, value_type);
    if (!table)
	rb_grn_context_check(context, rb_ary_new4(argc, argv));
    rb_table = GRNOBJECT2RVAL(klass, context, table, GRN_TRUE);

    if (!NIL_P(rb_default_tokenizer))
	rb_funcall(rb_table, rb_intern("default_tokenizer="), 1,
		   rb_default_tokenizer);

    if (rb_block_given_p())
        return rb_ensure(rb_yield, rb_table, rb_grn_object_close, rb_table);
    else
        return rb_table;
}
Beispiel #18
0
static void write_name_and_type(bson_buffer* buffer, VALUE name, char type) {
    buffer_write_bytes(buffer, &type, 1);
    buffer_write_bytes(buffer, RSTRING_PTR(name), RSTRING_LEN(name));
    buffer_write_bytes(buffer, &zero, 1);
}
Beispiel #19
0
static void putmsg(VALUE msg_rb, const Descriptor* desc,
                   upb_sink *sink, int depth) {
  MessageHeader* msg;
  upb_msg_field_iter i;
  upb_status status;

  upb_sink_startmsg(sink);

  // Protect against cycles (possible because users may freely reassign message
  // and repeated fields) by imposing a maximum recursion depth.
  if (depth > ENCODE_MAX_NESTING) {
    rb_raise(rb_eRuntimeError,
             "Maximum recursion depth exceeded during encoding.");
  }

  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

  for (upb_msg_field_begin(&i, desc->msgdef);
       !upb_msg_field_done(&i);
       upb_msg_field_next(&i)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    bool is_matching_oneof = false;
    uint32_t offset =
        desc->layout->fields[upb_fielddef_index(f)].offset +
        sizeof(MessageHeader);

    if (upb_fielddef_containingoneof(f)) {
      uint32_t oneof_case_offset =
          desc->layout->fields[upb_fielddef_index(f)].case_offset +
          sizeof(MessageHeader);
      // For a oneof, check that this field is actually present -- skip all the
      // below if not.
      if (DEREF(msg, oneof_case_offset, uint32_t) !=
          upb_fielddef_number(f)) {
        continue;
      }
      // Otherwise, fall through to the appropriate singular-field handler
      // below.
      is_matching_oneof = true;
    }

    if (is_map_field(f)) {
      VALUE map = DEREF(msg, offset, VALUE);
      if (map != Qnil) {
        putmap(map, f, sink, depth);
      }
    } else if (upb_fielddef_isseq(f)) {
      VALUE ary = DEREF(msg, offset, VALUE);
      if (ary != Qnil) {
        putary(ary, f, sink, depth);
      }
    } else if (upb_fielddef_isstring(f)) {
      VALUE str = DEREF(msg, offset, VALUE);
      if (is_matching_oneof || RSTRING_LEN(str) > 0) {
        putstr(str, f, sink);
      }
    } else if (upb_fielddef_issubmsg(f)) {
      putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
    } else {
      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));

#define T(upbtypeconst, upbtype, ctype, default_value)                \
  case upbtypeconst: {                                                \
      ctype value = DEREF(msg, offset, ctype);                        \
      if (is_matching_oneof || value != default_value) {              \
        upb_sink_put##upbtype(sink, sel, value);                      \
      }                                                               \
    }                                                                 \
    break;

      switch (upb_fielddef_type(f)) {
        T(UPB_TYPE_FLOAT,  float,  float, 0.0)
        T(UPB_TYPE_DOUBLE, double, double, 0.0)
        T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
        case UPB_TYPE_ENUM:
        T(UPB_TYPE_INT32,  int32,  int32_t, 0)
        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
        T(UPB_TYPE_INT64,  int64,  int64_t, 0)
        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)

        case UPB_TYPE_STRING:
        case UPB_TYPE_BYTES:
        case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
      }

#undef T

    }
  }

  upb_sink_endmsg(sink, &status);
}
Beispiel #20
0
static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow_id) {
    bson_buffer* buffer = (bson_buffer*)NUM2LL(rb_ary_entry(extra, 0));
    VALUE check_keys = rb_ary_entry(extra, 1);

    if (TYPE(key) == T_SYMBOL) {
        // TODO better way to do this... ?
        key = rb_str_new2(rb_id2name(SYM2ID(key)));
    }

    if (TYPE(key) != T_STRING) {
        rb_raise(rb_eTypeError, "keys must be strings or symbols");
    }

    if (!allow_id && strcmp("_id", RSTRING_PTR(key)) == 0) {
        return ST_CONTINUE;
    }

    if (check_keys == Qtrue) {
        int i;
        if (RSTRING_LEN(key) > 0 && RSTRING_PTR(key)[0] == '$') {
            rb_raise(InvalidName, "key must not start with '$'");
        }
        for (i = 0; i < RSTRING_LEN(key); i++) {
            if (RSTRING_PTR(key)[i] == '.') {
                rb_raise(InvalidName, "key must not contain '.'");
            }
        }
    }

    switch(TYPE(value)) {
    case T_BIGNUM:
    case T_FIXNUM:
        {
            if (rb_funcall(value, rb_intern(">"), 1, LL2NUM(9223372036854775807LL)) == Qtrue ||
                rb_funcall(value, rb_intern("<"), 1, LL2NUM(-9223372036854775808LL)) == Qtrue) {
                rb_raise(rb_eRangeError, "MongoDB can only handle 8-byte ints");
            }
            if (rb_funcall(value, rb_intern(">"), 1, INT2NUM(2147483647L)) == Qtrue ||
                rb_funcall(value, rb_intern("<"), 1, INT2NUM(-2147483648L)) == Qtrue) {
                long long ll_value;
                write_name_and_type(buffer, key, 0x12);
                ll_value = NUM2LL(value);
                buffer_write_bytes(buffer, (char*)&ll_value, 8);
            } else {
                int int_value;
                write_name_and_type(buffer, key, 0x10);
                int_value = NUM2LL(value);
                buffer_write_bytes(buffer, (char*)&int_value, 4);
            }
            break;
        }
    case T_TRUE:
        {
            write_name_and_type(buffer, key, 0x08);
            buffer_write_bytes(buffer, &one, 1);
            break;
        }
    case T_FALSE:
        {
            write_name_and_type(buffer, key, 0x08);
            buffer_write_bytes(buffer, &zero, 1);
            break;
        }
    case T_FLOAT:
        {
            double d = NUM2DBL(value);
            write_name_and_type(buffer, key, 0x01);
            buffer_write_bytes(buffer, (char*)&d, 8);
            break;
        }
    case T_NIL:
        {
            write_name_and_type(buffer, key, 0x0A);
            break;
        }
    case T_HASH:
        {
            write_name_and_type(buffer, key, 0x03);
            write_doc(buffer, value, check_keys);
            break;
        }
    case T_ARRAY:
        {
            int start_position, length_location, items, i, obj_length;
            VALUE* values;

            write_name_and_type(buffer, key, 0x04);
            start_position = buffer->position;

            // save space for length
            length_location = buffer_save_bytes(buffer, 4);

            items = RARRAY_LEN(value);
            values = RARRAY_PTR(value);
            for(i = 0; i < items; i++) {
                char* name;
                VALUE key;
                INT2STRING(&name, i);
                key = rb_str_new2(name);
                write_element(key, values[i], pack_extra(buffer, check_keys));
                free(name);
            }

            // write null byte and fill in length
            buffer_write_bytes(buffer, &zero, 1);
            obj_length = buffer->position - start_position;
            memcpy(buffer->buffer + length_location, &obj_length, 4);
            break;
        }
    case T_STRING:
        {
            if (strcmp(rb_class2name(RBASIC(value)->klass),
                       "Mongo::Code") == 0) {
                int start_position, length_location, length, total_length;
                write_name_and_type(buffer, key, 0x0F);

                start_position = buffer->position;
                length_location = buffer_save_bytes(buffer, 4);

                length = RSTRING_LEN(value) + 1;
                buffer_write_bytes(buffer, (char*)&length, 4);
                buffer_write_bytes(buffer, RSTRING_PTR(value), length - 1);
                buffer_write_bytes(buffer, &zero, 1);
                write_doc(buffer, rb_funcall(value, rb_intern("scope"), 0), Qfalse);

                total_length = buffer->position - start_position;
                memcpy(buffer->buffer + length_location, &total_length, 4);

                break;
            } else {
                int length = RSTRING_LEN(value) + 1;
                write_name_and_type(buffer, key, 0x02);
                buffer_write_bytes(buffer, (char*)&length, 4);
                buffer_write_bytes(buffer, RSTRING_PTR(value), length - 1);
                buffer_write_bytes(buffer, &zero, 1);
                break;
            }
        }
    case T_SYMBOL:
        {
            const char* str_value = rb_id2name(SYM2ID(value));
            int length = strlen(str_value) + 1;
            write_name_and_type(buffer, key, 0x0E);
            buffer_write_bytes(buffer, (char*)&length, 4);
            buffer_write_bytes(buffer, str_value, length);
            break;
        }
    case T_OBJECT:
        {
            // TODO there has to be a better way to do these checks...
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "Mongo::Binary") == 0 ||
                strcmp(cls, "ByteBuffer") == 0) {
                const char subtype = strcmp(cls, "ByteBuffer") ?
                    (const char)FIX2INT(rb_funcall(value, rb_intern("subtype"), 0)) : 2;
                VALUE string_data = rb_funcall(value, rb_intern("to_s"), 0);
                int length = RSTRING_LEN(string_data);
                write_name_and_type(buffer, key, 0x05);
                if (subtype == 2) {
                    const int other_length = length + 4;
                    buffer_write_bytes(buffer, (const char*)&other_length, 4);
                    buffer_write_bytes(buffer, &subtype, 1);
                }
                buffer_write_bytes(buffer, (const char*)&length, 4);
                if (subtype != 2) {
                    buffer_write_bytes(buffer, &subtype, 1);
                }
                buffer_write_bytes(buffer, RSTRING_PTR(string_data), length);
                break;
            }
            if (strcmp(cls, "Mongo::ObjectID") == 0) {
                VALUE as_array = rb_funcall(value, rb_intern("to_a"), 0);
                int i;
                write_name_and_type(buffer, key, 0x07);
                for (i = 0; i < 12; i++) {
                    char byte = (char)FIX2INT(RARRAY_PTR(as_array)[i]);
                    buffer_write_bytes(buffer, &byte, 1);
                }
                break;
            }
            if (strcmp(cls, "Mongo::DBRef") == 0) {
                int start_position, length_location, obj_length;
                VALUE ns, oid;
                write_name_and_type(buffer, key, 0x03);

                start_position = buffer->position;

                // save space for length
                length_location = buffer_save_bytes(buffer, 4);

                ns = rb_funcall(value, rb_intern("namespace"), 0);
                write_element(rb_str_new2("$ref"), ns, pack_extra(buffer, Qfalse));
                oid = rb_funcall(value, rb_intern("object_id"), 0);
                write_element(rb_str_new2("$id"), oid, pack_extra(buffer, Qfalse));

                // write null byte and fill in length
                buffer_write_bytes(buffer, &zero, 1);
                obj_length = buffer->position - start_position;
                memcpy(buffer->buffer + length_location, &obj_length, 4);
                break;
            }
        }
    case T_DATA:
        {
            // TODO again, is this really the only way to do this?
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "Time") == 0) {
                double t = NUM2DBL(rb_funcall(value, rb_intern("to_f"), 0));
                long long time_since_epoch = (long long)round(t * 1000);
                write_name_and_type(buffer, key, 0x09);
                buffer_write_bytes(buffer, (const char*)&time_since_epoch, 8);
                break;
            }
        }
    case T_REGEXP:
        {
            int length = RREGEXP_SRC_LEN(value);
            char* pattern = (char*)RREGEXP_SRC_PTR(value);
            long flags = RREGEXP(value)->ptr->options;
            VALUE has_extra;

            write_name_and_type(buffer, key, 0x0B);

            buffer_write_bytes(buffer, pattern, length);
            buffer_write_bytes(buffer, &zero, 1);

            if (flags & IGNORECASE) {
                char ignorecase = 'i';
                buffer_write_bytes(buffer, &ignorecase, 1);
            }
            if (flags & MULTILINE) {
                char multiline = 'm';
                buffer_write_bytes(buffer, &multiline, 1);
            }
            if (flags & EXTENDED) {
                char extended = 'x';
                buffer_write_bytes(buffer, &extended, 1);
            }

            has_extra = rb_funcall(value, rb_intern("respond_to?"), 1, rb_str_new2("extra_options_str"));
            if (TYPE(has_extra) == T_TRUE) {
                VALUE extra = rb_funcall(value, rb_intern("extra_options_str"), 0);
                int old_position = buffer->position;
                buffer_write_bytes(buffer, RSTRING_PTR(extra), RSTRING_LEN(extra));
                qsort(buffer->buffer + old_position, RSTRING_LEN(extra), sizeof(char), cmp_char);
            }
            buffer_write_bytes(buffer, &zero, 1);

            break;
        }
    default:
        {
            rb_raise(rb_eTypeError, "no c encoder for this type yet (%d)", TYPE(value));
            break;
        }
    }
    return ST_CONTINUE;
}
Beispiel #21
0
VALUE string_spec_rb_str_resize_RSTRING_LEN(VALUE self, VALUE str, VALUE size) {
  VALUE modified = rb_str_resize(str, FIX2INT(size));
  return INT2FIX(RSTRING_LEN(modified));
}
Beispiel #22
0
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// http://man7.org/linux/man-pages/man2/msgsnd.2.html
//
// Sends a message to the message queue.
VALUE
sysvmq_send(int argc, VALUE *argv, VALUE self)
{
  VALUE message;
  VALUE priority = INT2FIX(1);
  VALUE flags = INT2FIX(0);
  sysvmq_blocking_call_t blocking;
  sysvmq_t* sysv;

  if (argc > 3 || argc == 0) {
    rb_raise(rb_eArgError, "Wrong number of arguments (1..3)");
  }

  message  = argv[0];
  if (argc >= 2) priority = argv[1];
  if (argc == 3) flags    = argv[2];

  message = rb_funcall(message, rb_intern("to_s"), 0);

  TypedData_Get_Struct(self, sysvmq_t, &sysvmq_type, sysv);

  Check_Type(flags,    T_FIXNUM);
  Check_Type(priority, T_FIXNUM);
  // TODO: Call to_s on message if it responds to

  // Attach blocking call parameters to the struct passed to the blocking
  // function wrapper.
  blocking.flags = FIX2INT(flags);
  blocking.size  = RSTRING_LEN(message);
  blocking.sysv  = sysv;
  // See msgrcv(2) wrapper
  blocking.error  = UNINITIALIZED_ERROR;
  blocking.length = UNINITIALIZED_ERROR;

  // The buffer can be obtained from `sysvmq_maybe_blocking_send`, instead of
  // passing it, set it directly on the instance struct.
  sysv->msgbuf->mtype = FIX2INT(priority);

  if (blocking.size > sysv->buffer_size) {
    rb_raise(rb_eArgError, "Size of message is bigger than buffer size.");
  }

  // TODO: Can a string copy be avoided?
  memcpy(sysv->msgbuf->mtext, RSTRING_PTR(message), blocking.size);

  // Non-blocking call, skip the expensive GVL release/acquire
  if ((blocking.flags & IPC_NOWAIT) == IPC_NOWAIT) {
    while(sysvmq_maybe_blocking_send(&blocking) == NULL && blocking.error < 0) {
      if (errno == EINTR) {
        continue;
      }

      rb_sys_fail("Failed sending message to queue");
    }
  } else {
    // msgsnd(2) can block waiting for a message, if IPC_NOWAIT is not passed.
    // We unlock the GVL waiting for the call so other threads (e.g. signal
    // handling) can continue to work.
    while (WITHOUT_GVL(sysvmq_maybe_blocking_send, &blocking, RUBY_UBF_IO, NULL) == NULL
            && blocking.error < 0) {
      if (errno == EINTR || blocking.error == UNINITIALIZED_ERROR) {
        continue;
      }

      rb_sys_fail("Failed sending message to queue");
    }
  }

  return message;
}
Beispiel #23
0
VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) {
  rb_str_set_len(str, NUM2LONG(len));

  return INT2FIX(RSTRING_LEN(str));
}
Beispiel #24
0
static void setup_send_buffer(struct rw_args *x, VALUE buffer)
{
	buffer = rb_obj_as_string(buffer);
	x->msg_ptr = RSTRING_PTR(buffer);
	x->msg_len = (size_t)RSTRING_LEN(buffer);
}
Beispiel #25
0
MRB_API mrb_sym
mrb_intern_str(mrb_state *mrb, mrb_value str)
{
  return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
}
Beispiel #26
0
void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
    VALUE str, outBuff, otherObj;
    yajl_encoder_wrapper * w = wrapper;
    yajl_gen_status status;
    int idx = 0;
    const unsigned char * buffer;
    const char * cptr;
    unsigned int len;

    if (io != Qnil || w->on_progress_callback != Qnil) {
        status = yajl_gen_get_buf(w->encoder, &buffer, &len);
        if (len >= WRITE_BUFSIZE) {
            outBuff = rb_str_new((const char *)buffer, len);
            if (io != Qnil) {
                rb_io_write(io, outBuff);
            } else if (w->on_progress_callback != Qnil) {
                rb_funcall(w->on_progress_callback, intern_call, 1, outBuff);
            }
            yajl_gen_clear(w->encoder);
        }
    }

    switch (TYPE(obj)) {
        case T_HASH:
            status = yajl_gen_map_open(w->encoder);

            /* TODO: itterate through keys in the hash */
            VALUE keys = rb_funcall(obj, intern_keys, 0);
            VALUE entry, keyStr;
            for(idx=0; idx<RARRAY_LEN(keys); idx++) {
                entry = rb_ary_entry(keys, idx);
                keyStr = rb_funcall(entry, intern_to_s, 0); /* key must be a string */
                /* the key */
                yajl_encode_part(w, keyStr, io);
                /* the value */
                yajl_encode_part(w, rb_hash_aref(obj, entry), io);
            }

            status = yajl_gen_map_close(w->encoder);
            break;
        case T_ARRAY:
            status = yajl_gen_array_open(w->encoder);
            for(idx=0; idx<RARRAY_LEN(obj); idx++) {
                otherObj = rb_ary_entry(obj, idx);
                yajl_encode_part(w, otherObj, io);
            }
            status = yajl_gen_array_close(w->encoder);
            break;
        case T_NIL:
            status = yajl_gen_null(w->encoder);
            break;
        case T_TRUE:
            status = yajl_gen_bool(w->encoder, 1);
            break;
        case T_FALSE:
            status = yajl_gen_bool(w->encoder, 0);
            break;
        case T_FIXNUM:
        case T_FLOAT:
        case T_BIGNUM:
            str = rb_funcall(obj, intern_to_s, 0);
            cptr = RSTRING_PTR(str);
            len = RSTRING_LEN(str);
            if (memcmp(cptr, "NaN", 3) == 0 || memcmp(cptr, "Infinity", 8) == 0 || memcmp(cptr, "-Infinity", 9) == 0) {
                rb_raise(cEncodeError, "'%s' is an invalid number", cptr);
            }
            status = yajl_gen_number(w->encoder, cptr, len);
            break;
        default:
            if (rb_respond_to(obj, intern_to_json)) {
                str = rb_funcall(obj, intern_to_json, 0);
                cptr = RSTRING_PTR(str);
                len = RSTRING_LEN(str);
                status = yajl_gen_number(w->encoder, cptr, len);
            } else {
                if (TYPE(obj) != T_STRING) {
                    str = rb_funcall(obj, intern_to_s, 0);
                }else {
                    str = obj;
                }
                cptr = RSTRING_PTR(str);
                len = RSTRING_LEN(str);
                status = yajl_gen_string(w->encoder, (const unsigned char *)cptr, len);
            }
            break;
    }
}