From 58daab21cd043e1dc37024a7f99b396788372918 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:48 +0100 Subject: Merging upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../deps/mruby/mrbgems/mruby-struct/src/struct.c | 714 +++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c (limited to 'web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c') diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c new file mode 100644 index 000000000..67762a948 --- /dev/null +++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c @@ -0,0 +1,714 @@ +/* +** struct.c - Struct class +** +** See Copyright Notice in mruby.h +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RSTRUCT_LEN(st) RARRAY_LEN(st) +#define RSTRUCT_PTR(st) RARRAY_PTR(st) + +static struct RClass * +struct_class(mrb_state *mrb) +{ + return mrb_class_get(mrb, "Struct"); +} + +static inline mrb_value +struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id) +{ + struct RClass* kclass; + struct RClass* sclass = struct_class(mrb); + mrb_value ans; + + for (;;) { + ans = mrb_iv_get(mrb, c, id); + if (!mrb_nil_p(ans)) return ans; + kclass = RCLASS_SUPER(c); + if (kclass == 0 || kclass == sclass) + return mrb_nil_value(); + c = mrb_obj_value(kclass); + } +} + +static mrb_value +struct_s_members(mrb_state *mrb, struct RClass *klass) +{ + mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__")); + + if (mrb_nil_p(members)) { + mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct"); + } + if (!mrb_array_p(members)) { + mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); + } + return members; +} + +static mrb_value +struct_members(mrb_state *mrb, mrb_value s) +{ + mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s)); + if (!mrb_array_p(s)) { + mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); + } + if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { + if (RSTRUCT_LEN(s) == 0) { /* probably uninitialized */ + mrb_ary_resize(mrb, s, RARRAY_LEN(members)); + } + else { + mrb_raisef(mrb, E_TYPE_ERROR, + "struct size differs (%S required %S given)", + mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); + } + } + return members; +} + +static mrb_value +mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass) +{ + mrb_value members, ary; + + members = struct_s_members(mrb, mrb_class_ptr(klass)); + ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members)); + mrb_ary_replace(mrb, ary, members); + return ary; +} + +static void +mrb_struct_modify(mrb_state *mrb, mrb_value strct) +{ + if (MRB_FROZEN_P(mrb_basic_ptr(strct))) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen struct"); + } + + mrb_write_barrier(mrb, mrb_basic_ptr(strct)); +} + +/* 15.2.18.4.6 */ +/* + * call-seq: + * struct.members -> array + * + * Returns an array of strings representing the names of the instance + * variables. + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joe.members #=> [:name, :address, :zip] + */ + +static mrb_value +mrb_struct_members(mrb_state *mrb, mrb_value obj) +{ + return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); +} + +static mrb_value struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id); + +static mrb_value +mrb_struct_ref(mrb_state *mrb, mrb_value obj) +{ + return struct_aref_sym(mrb, obj, mrb->c->ci->mid); +} + +static mrb_sym +mrb_id_attrset(mrb_state *mrb, mrb_sym id) +{ + const char *name; + char *buf; + mrb_int len; + mrb_sym mid; + + name = mrb_sym2name_len(mrb, id, &len); + buf = (char *)mrb_malloc(mrb, (size_t)len+2); + memcpy(buf, name, (size_t)len); + buf[len] = '='; + buf[len+1] = '\0'; + + mid = mrb_intern(mrb, buf, len+1); + mrb_free(mrb, buf); + return mid; +} + +static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val); + +static mrb_value +mrb_struct_set_m(mrb_state *mrb, mrb_value obj) +{ + mrb_value val; + + const char *name; + mrb_int slen; + mrb_sym mid; + + mrb_get_args(mrb, "o", &val); + + /* get base id */ + name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen); + mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */ + + return mrb_struct_aset_sym(mrb, obj, mid, val); +} + +static mrb_bool +is_local_id(mrb_state *mrb, const char *name) +{ + if (!name) return FALSE; + return !ISUPPER(name[0]); +} + +static mrb_bool +is_const_id(mrb_state *mrb, const char *name) +{ + if (!name) return FALSE; + return ISUPPER(name[0]); +} + +static void +make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c) +{ + const mrb_value *ptr_members = RARRAY_PTR(members); + mrb_int i; + mrb_int len = RARRAY_LEN(members); + int ai = mrb_gc_arena_save(mrb); + + for (i=0; ibasic.c->super = c->c; */ + make_struct_define_accessors(mrb, members, c); + return nstr; +} + +/* 15.2.18.3.1 */ +/* + * call-seq: + * Struct.new( [aString] [, aSym]+> ) -> StructClass + * StructClass.new(arg, ...) -> obj + * StructClass[arg, ...] -> obj + * + * Creates a new class, named by aString, containing accessor + * methods for the given symbols. If the name aString is + * omitted, an anonymous structure class will be created. Otherwise, + * the name of this struct will appear as a constant in class + * Struct, so it must be unique for all + * Structs in the system and should start with a capital + * letter. Assigning a structure class to a constant effectively gives + * the class the name of the constant. + * + * Struct::new returns a new Class object, + * which can then be used to create specific instances of the new + * structure. The number of actual parameters must be + * less than or equal to the number of attributes defined for this + * class; unset parameters default to nil. Passing too many + * parameters will raise an ArgumentError. + * + * The remaining methods listed in this section (class and instance) + * are defined for this generated class. + * + * # Create a structure with a name in Struct + * Struct.new("Customer", :name, :address) #=> Struct::Customer + * Struct::Customer.new("Dave", "123 Main") #=> # + * + * # Create a structure named by its constant + * Customer = Struct.new(:name, :address) #=> Customer + * Customer.new("Dave", "123 Main") #=> # + */ +static mrb_value +mrb_struct_s_def(mrb_state *mrb, mrb_value klass) +{ + mrb_value name, rest; + mrb_value *pargv; + mrb_int argcnt; + mrb_int i; + mrb_value b, st; + mrb_sym id; + mrb_value *argv; + mrb_int argc; + + name = mrb_nil_value(); + mrb_get_args(mrb, "*&", &argv, &argc, &b); + if (argc == 0) { /* special case to avoid crash */ + rest = mrb_ary_new(mrb); + } + else { + if (argc > 0) name = argv[0]; + pargv = &argv[1]; + argcnt = argc-1; + if (!mrb_nil_p(name) && mrb_symbol_p(name)) { + /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ + name = mrb_nil_value(); + pargv = &argv[0]; + argcnt++; + } + rest = mrb_ary_new_from_values(mrb, argcnt, pargv); + for (i=0; i anObject + * struct[fixnum] -> anObject + * + * Attribute Reference---Returns the value of the instance variable + * named by symbol, or indexed (0..length-1) by + * fixnum. Will raise NameError if the named + * variable does not exist, or IndexError if the index is + * out of range. + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * + * joe["name"] #=> "Joe Smith" + * joe[:name] #=> "Joe Smith" + * joe[0] #=> "Joe Smith" + */ +static mrb_value +mrb_struct_aref(mrb_state *mrb, mrb_value s) +{ + mrb_value idx; + + mrb_get_args(mrb, "o", &idx); + if (mrb_string_p(idx)) { + mrb_value sym = mrb_check_intern_str(mrb, idx); + + if (mrb_nil_p(sym)) { + mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx); + } + idx = sym; + } + if (mrb_symbol_p(idx)) { + return struct_aref_sym(mrb, s, mrb_symbol(idx)); + } + return struct_aref_int(mrb, s, mrb_int(mrb, idx)); +} + +static mrb_value +mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) +{ + mrb_value members, *ptr; + const mrb_value *ptr_members; + mrb_int i, len; + + members = struct_members(mrb, s); + len = RARRAY_LEN(members); + ptr = RSTRUCT_PTR(s); + ptr_members = RARRAY_PTR(members); + for (i=0; i obj + * struct[fixnum] = obj -> obj + * + * Attribute Assignment---Assigns to the instance variable named by + * symbol or fixnum the value obj and + * returns it. Will raise a NameError if the named + * variable does not exist, or an IndexError if the index + * is out of range. + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * + * joe["name"] = "Luke" + * joe[:zip] = "90210" + * + * joe.name #=> "Luke" + * joe.zip #=> "90210" + */ + +static mrb_value +mrb_struct_aset(mrb_state *mrb, mrb_value s) +{ + mrb_int i; + mrb_value idx; + mrb_value val; + + mrb_get_args(mrb, "oo", &idx, &val); + + if (mrb_string_p(idx)) { + mrb_value sym = mrb_check_intern_str(mrb, idx); + + if (mrb_nil_p(sym)) { + mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx); + } + idx = sym; + } + if (mrb_symbol_p(idx)) { + return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val); + } + + i = mrb_int(mrb, idx); + if (i < 0) i = RSTRUCT_LEN(s) + i; + if (i < 0) { + mrb_raisef(mrb, E_INDEX_ERROR, + "offset %S too small for struct(size:%S)", + mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); + } + if (RSTRUCT_LEN(s) <= i) { + mrb_raisef(mrb, E_INDEX_ERROR, + "offset %S too large for struct(size:%S)", + mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); + } + mrb_struct_modify(mrb, s); + return RSTRUCT_PTR(s)[i] = val; +} + +/* 15.2.18.4.1 */ +/* + * call-seq: + * struct == other_struct -> true or false + * + * Equality---Returns true if other_struct is + * equal to this one: they must be of the same class as generated by + * Struct::new, and the values of all instance variables + * must be equal (according to Object#==). + * + * Customer = Struct.new(:name, :address, :zip) + * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) + * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345) + * joe == joejr #=> true + * joe == jane #=> false + */ + +static mrb_value +mrb_struct_equal(mrb_state *mrb, mrb_value s) +{ + mrb_value s2; + mrb_value *ptr, *ptr2; + mrb_int i, len; + + mrb_get_args(mrb, "o", &s2); + if (mrb_obj_equal(mrb, s, s2)) { + return mrb_true_value(); + } + if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { + return mrb_false_value(); + } + if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { + mrb_bug(mrb, "inconsistent struct"); /* should never happen */ + } + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + for (i=0; i true or false + * + * Two structures are equal if they are the same object, or if all their + * fields are equal (using eql?). + */ +static mrb_value +mrb_struct_eql(mrb_state *mrb, mrb_value s) +{ + mrb_value s2; + mrb_value *ptr, *ptr2; + mrb_int i, len; + + mrb_get_args(mrb, "o", &s2); + if (mrb_obj_equal(mrb, s, s2)) { + return mrb_true_value(); + } + if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { + return mrb_false_value(); + } + if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { + mrb_bug(mrb, "inconsistent struct"); /* should never happen */ + } + ptr = RSTRUCT_PTR(s); + ptr2 = RSTRUCT_PTR(s2); + len = RSTRUCT_LEN(s); + for (i=0; i Fixnum + * struct.size -> Fixnum + * + * Returns number of struct members. + */ +static mrb_value +mrb_struct_len(mrb_state *mrb, mrb_value self) +{ + return mrb_fixnum_value(RSTRUCT_LEN(self)); +} + +/* + * call-seq: + * struct.to_a -> array + * struct.values -> array + * + * Create an array from struct values. + */ +static mrb_value +mrb_struct_to_a(mrb_state *mrb, mrb_value self) +{ + return mrb_ary_new_from_values(mrb, RSTRUCT_LEN(self), RSTRUCT_PTR(self)); +} + +/* + * call-seq: + * struct.to_h -> hash + * + * Create a hash from member names and struct values. + */ +static mrb_value +mrb_struct_to_h(mrb_state *mrb, mrb_value self) +{ + mrb_value members, ret; + mrb_int i; + + members = struct_members(mrb, self); + ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members)); + + for (i = 0; i < RARRAY_LEN(members); ++i) { + mrb_hash_set(mrb, ret, RARRAY_PTR(members)[i], RSTRUCT_PTR(self)[i]); + } + + return ret; +} + +static mrb_value +mrb_struct_values_at(mrb_state *mrb, mrb_value self) +{ + mrb_int argc; + mrb_value *argv; + + mrb_get_args(mrb, "*", &argv, &argc); + + return mrb_get_values_at(mrb, self, RSTRUCT_LEN(self), argc, argv, struct_aref_int); +} + +/* + * A Struct is a convenient way to bundle a number of + * attributes together, using accessor methods, without having to write + * an explicit class. + * + * The Struct class is a generator of specific classes, + * each one of which is defined to hold a set of variables and their + * accessors. In these examples, we'll call the generated class + * "CustomerClass," and we'll show an example instance of that + * class as "CustomerInst." + * + * In the descriptions that follow, the parameter symbol refers + * to a symbol, which is either a quoted string or a + * Symbol (such as :name). + */ +void +mrb_mruby_struct_gem_init(mrb_state* mrb) +{ + struct RClass *st; + st = mrb_define_class(mrb, "Struct", mrb->object_class); + MRB_SET_INSTANCE_TT(st, MRB_TT_ARRAY); + + mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, MRB_ARGS_ANY()); /* 15.2.18.3.1 */ + + mrb_define_method(mrb, st, "==", mrb_struct_equal, MRB_ARGS_REQ(1)); /* 15.2.18.4.1 */ + mrb_define_method(mrb, st, "[]", mrb_struct_aref, MRB_ARGS_REQ(1)); /* 15.2.18.4.2 */ + mrb_define_method(mrb, st, "[]=", mrb_struct_aset, MRB_ARGS_REQ(2)); /* 15.2.18.4.3 */ + mrb_define_method(mrb, st, "members", mrb_struct_members, MRB_ARGS_NONE()); /* 15.2.18.4.6 */ + mrb_define_method(mrb, st, "initialize", mrb_struct_initialize, MRB_ARGS_ANY()); /* 15.2.18.4.8 */ + mrb_define_method(mrb, st, "initialize_copy", mrb_struct_init_copy, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */ + mrb_define_method(mrb, st, "eql?", mrb_struct_eql, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */ + + mrb_define_method(mrb, st, "size", mrb_struct_len, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "length", mrb_struct_len, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "to_a", mrb_struct_to_a, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "values", mrb_struct_to_a, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "to_h", mrb_struct_to_h, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_ANY()); +} + +void +mrb_mruby_struct_gem_final(mrb_state* mrb) +{ +} -- cgit v1.2.3