summaryrefslogtreecommitdiff
path: root/internal/struct.h
diff options
context:
space:
mode:
Diffstat (limited to 'internal/struct.h')
-rw-r--r--internal/struct.h140
1 files changed, 140 insertions, 0 deletions
diff --git a/internal/struct.h b/internal/struct.h
new file mode 100644
index 0000000000..d3c8157393
--- /dev/null
+++ b/internal/struct.h
@@ -0,0 +1,140 @@
+#ifndef INTERNAL_STRUCT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_STRUCT_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @brief Internal header for Struct.
+ */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for struct RBasic */
+
+/* Flags of RStruct
+ *
+ * 1-7: RSTRUCT_EMBED_LEN
+ * If non-zero, the struct is embedded (its contents follow the
+ * header, rather than being on a separately allocated buffer) and
+ * these bits are the length of the Struct.
+ * 8: RSTRUCT_GEN_FIELDS
+ * The struct is embedded and has no space left to store the
+ * IMEMO/fields reference. Any ivar this struct may have will be in
+ * the generic_fields_tbl. This flag doesn't imply the struct has
+ * ivars.
+ */
+enum {
+ RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
+ RUBY_FL_USER3 | RUBY_FL_USER2 | RUBY_FL_USER1,
+ RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
+ RSTRUCT_GEN_FIELDS = RUBY_FL_USER8,
+};
+
+struct RStruct {
+ struct RBasic basic;
+ union {
+ struct {
+ long len;
+ const VALUE *ptr;
+ VALUE fields_obj;
+ } heap;
+ /* This is a length 1 array because:
+ * 1. GCC has a bug that does not optimize C flexible array members
+ * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
+ * 2. Zero length arrays are not supported by all compilers
+ */
+ const VALUE ary[1];
+ } as;
+};
+
+#define RSTRUCT(obj) ((struct RStruct *)(obj))
+
+/* struct.c */
+VALUE rb_struct_init_copy(VALUE copy, VALUE s);
+VALUE rb_struct_lookup(VALUE s, VALUE idx);
+VALUE rb_struct_s_keyword_init(VALUE klass);
+static inline long RSTRUCT_EMBED_LEN(VALUE st);
+static inline long RSTRUCT_LEN_RAW(VALUE st);
+static inline int RSTRUCT_LENINT(VALUE st);
+static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st);
+static inline void RSTRUCT_SET_RAW(VALUE st, long k, VALUE v);
+static inline VALUE RSTRUCT_GET_RAW(VALUE st, long k);
+
+static inline long
+RSTRUCT_EMBED_LEN(VALUE st)
+{
+ long ret = FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK);
+ ret >>= RSTRUCT_EMBED_LEN_SHIFT;
+ return ret;
+}
+
+static inline long
+RSTRUCT_LEN_RAW(VALUE st)
+{
+ if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
+ return RSTRUCT_EMBED_LEN(st);
+ }
+ else {
+ return RSTRUCT(st)->as.heap.len;
+ }
+}
+
+static inline int
+RSTRUCT_LENINT(VALUE st)
+{
+ return rb_long2int(RSTRUCT_LEN_RAW(st));
+}
+
+static inline const VALUE *
+RSTRUCT_CONST_PTR(VALUE st)
+{
+ const struct RStruct *p = RSTRUCT(st);
+
+ if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
+ return p->as.ary;
+ }
+ else {
+ return p->as.heap.ptr;
+ }
+}
+
+static inline void
+RSTRUCT_SET_RAW(VALUE st, long k, VALUE v)
+{
+ RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[k], v);
+}
+
+static inline VALUE
+RSTRUCT_GET_RAW(VALUE st, long k)
+{
+ return RSTRUCT_CONST_PTR(st)[k];
+}
+
+static inline VALUE
+RSTRUCT_FIELDS_OBJ(VALUE st)
+{
+ const long embed_len = RSTRUCT_EMBED_LEN(st);
+ VALUE fields_obj;
+ if (embed_len) {
+ RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
+ fields_obj = RSTRUCT_GET_RAW(st, embed_len);
+ }
+ else {
+ fields_obj = RSTRUCT(st)->as.heap.fields_obj;
+ }
+ return fields_obj;
+}
+
+static inline void
+RSTRUCT_SET_FIELDS_OBJ(VALUE st, VALUE fields_obj)
+{
+ const long embed_len = RSTRUCT_EMBED_LEN(st);
+ if (embed_len) {
+ RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
+ RSTRUCT_SET_RAW(st, embed_len, fields_obj);
+ }
+ else {
+ RB_OBJ_WRITE(st, &RSTRUCT(st)->as.heap.fields_obj, fields_obj);
+ }
+}
+#endif /* INTERNAL_STRUCT_H */