ext/attribute_builder/attribute_builder.c in faml-0.3.1 vs ext/attribute_builder/attribute_builder.c in faml-0.3.2
- old
+ new
@@ -1,17 +1,19 @@
#include <ruby.h>
+#include <ruby/encoding.h>
#include <ruby/version.h>
+#include "houdini.h"
#if (RUBY_API_VERSION_MAJOR > 2) || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 1)
/* define nothing */
#else
# define RARRAY_AREF(a, i) RARRAY_PTR(a)[i]
# define rb_ary_new_capa rb_ary_new2
#endif
VALUE rb_mAttributeBuilder;
-static ID id_keys, id_sort_bang, id_uniq_bang, id_merge_bang, id_temple, id_utils, id_escape_html, id_gsub, id_to_s;
+static ID id_keys, id_sort_bang, id_uniq_bang, id_merge_bang, id_to_s;
static ID id_id, id_class, id_underscore, id_hyphen, id_space, id_equal;
static void
concat_array_attribute(VALUE attributes, VALUE hash, VALUE key)
{
@@ -47,17 +49,43 @@
struct normalize_data_i2_arg {
VALUE key, normalized;
};
+static VALUE
+substitute_underscores(VALUE str)
+{
+ int frozen;
+ long i, len;
+
+ /* gsub('_', '-') */
+ Check_Type(str, T_STRING);
+ len = RSTRING_LEN(str);
+ frozen = OBJ_FROZEN(str);
+ for (i = 0; i < len; i++) {
+ if (RSTRING_PTR(str)[i] == '_') {
+ if (frozen) {
+ str = rb_str_dup(str);
+ frozen = 0;
+ }
+ rb_str_update(str, i, 1, rb_const_get(rb_mAttributeBuilder, id_hyphen));
+ }
+ }
+
+ return str;
+}
+
static int
normalize_data_i2(VALUE key, VALUE value, VALUE ptr)
{
struct normalize_data_i2_arg *arg = (struct normalize_data_i2_arg *)ptr;
VALUE k = rb_funcall(arg->key, id_to_s, 0);
- k = rb_funcall(k, id_gsub, 2, rb_const_get(rb_mAttributeBuilder, id_underscore), rb_const_get(rb_mAttributeBuilder, id_hyphen));
+ k = substitute_underscores(k);
+ if (OBJ_FROZEN(k)) {
+ k = rb_str_dup(k);
+ }
rb_str_cat(k, "-", 1);
rb_str_append(k, key);
rb_hash_aset(arg->normalized, k, value);
return ST_CONTINUE;
}
@@ -72,11 +100,11 @@
arg.key = key;
arg.normalized = normalized;
rb_hash_foreach(normalize_data(value), normalize_data_i2, (VALUE)(&arg));
} else {
key = rb_funcall(key, id_to_s, 0);
- key = rb_funcall(key, id_gsub, 2, rb_const_get(rb_mAttributeBuilder, id_underscore), rb_const_get(rb_mAttributeBuilder, id_hyphen));
+ key = substitute_underscores(key);
rb_hash_aset(normalized, key, value);
}
return ST_CONTINUE;
}
@@ -89,38 +117,42 @@
normalized = rb_hash_new();
rb_hash_foreach(data, normalize_data_i, normalized);
return normalized;
}
+static int
+put_data_attribute(VALUE key, VALUE val, VALUE hash)
+{
+ VALUE k = rb_str_buf_new(5 + RSTRING_LEN(key));
+ rb_str_buf_cat(k, "data-", 5);
+ rb_str_buf_append(k, key);
+ rb_hash_aset(hash, k, val);
+ return ST_CONTINUE;
+}
+
static void
normalize(VALUE hash)
{
VALUE keys = rb_funcall(hash, id_keys, 0);
const long len = RARRAY_LEN(keys);
long i;
for (i = 0; i < len; i++) {
VALUE key = RARRAY_AREF(keys, i);
- const char *key_cstr = StringValueCStr(key);
VALUE value = rb_hash_lookup(hash, key);
- if (RB_TYPE_P(value, T_HASH) && strcmp(key_cstr, "data") == 0) {
- VALUE data, data_keys;
- long data_len, j;
+ VALUE key_str = key;
+ if (!RB_TYPE_P(key, T_STRING)) {
+ key_str = rb_funcall(key, id_to_s, 0);
+ }
+ if (RB_TYPE_P(value, T_HASH) && RSTRING_LEN(key_str) == 4 && memcmp(RSTRING_PTR(key_str), "data", 4) == 0) {
+ VALUE data;
+
rb_hash_delete(hash, key);
data = normalize_data(value);
- data_keys = rb_funcall(data, id_keys, 0);
- rb_funcall(data_keys, id_sort_bang, 0);
- data_len = RARRAY_LEN(data_keys);
- for (j = 0; j < data_len; j++) {
- VALUE data_key = RARRAY_AREF(data_keys, j);
- VALUE k = rb_str_buf_new(5 + RSTRING_LEN(data_key));
- rb_str_buf_cat(k, "data-", 5);
- rb_str_buf_append(k, data_key);
- rb_hash_aset(hash, k, rb_hash_lookup(data, data_key));
- }
+ rb_hash_foreach(data, put_data_attribute, hash);
} else if (!(RB_TYPE_P(value, T_TRUE) || RB_TYPE_P(value, T_FALSE) || NIL_P(value))) {
- rb_hash_aset(hash, key, rb_funcall(value, id_to_s, 0));
+ rb_hash_aset(hash, key_str, rb_funcall(value, id_to_s, 0));
}
}
}
static void
@@ -141,15 +173,18 @@
}
static void
put_attribute(VALUE buf, VALUE attr_quote, VALUE key, VALUE value)
{
- VALUE utils_class;
+ gh_buf ob = GH_BUF_INIT;
value = rb_funcall(value, id_to_s, 0);
- utils_class = rb_const_get(rb_const_get(rb_cObject, id_temple), id_utils);
- value = rb_funcall(utils_class, id_escape_html, 1, value);
+ Check_Type(value, T_STRING);
+ if (houdini_escape_html(&ob, (const uint8_t *)RSTRING_PTR(value), RSTRING_LEN(value))) {
+ value = rb_enc_str_new(ob.ptr, ob.size, rb_utf8_encoding());
+ gh_buf_free(&ob);
+ }
rb_ary_push(buf, rb_const_get(rb_mAttributeBuilder, id_space));
rb_ary_push(buf, key);
rb_ary_push(buf, rb_const_get(rb_mAttributeBuilder, id_equal));
rb_ary_push(buf, attr_quote);
@@ -158,12 +193,15 @@
}
static void
build_attribute(VALUE buf, VALUE attr_quote, int is_html, VALUE key, VALUE value)
{
- const char *key_cstr = StringValueCStr(key);
- if (strcmp(key_cstr, "class") == 0) {
+ if (!RB_TYPE_P(key, T_STRING)) {
+ key = rb_funcall(key, id_to_s, 0);
+ }
+ Check_Type(key, T_STRING);
+ if (RSTRING_LEN(key) == 5 && memcmp(RSTRING_PTR(key), "class", 5) == 0) {
long len;
Check_Type(value, T_ARRAY);
len = RARRAY_LEN(value);
if (len != 0) {
@@ -175,11 +213,11 @@
}
rb_funcall(ary, id_sort_bang, 0);
rb_funcall(ary, id_uniq_bang, 0);
put_attribute(buf, attr_quote, key, rb_ary_join(ary, rb_const_get(rb_mAttributeBuilder, id_space)));
}
- } else if (strcmp(key_cstr, "id") == 0) {
+ } else if (RSTRING_LEN(key) == 2 && memcmp(RSTRING_PTR(key), "id", 2) == 0) {
long len = RARRAY_LEN(value);
Check_Type(value, T_ARRAY);
len = RARRAY_LEN(value);
if (len != 0) {
@@ -248,27 +286,21 @@
id_keys = rb_intern("keys");
id_sort_bang = rb_intern("sort!");
id_uniq_bang = rb_intern("uniq!");
id_merge_bang = rb_intern("merge!");
- id_temple = rb_intern("Temple");
- id_utils = rb_intern("Utils");
- id_escape_html = rb_intern("escape_html");
- id_gsub = rb_intern("gsub");
id_to_s = rb_intern("to_s");
id_id = rb_intern("ID");
id_class = rb_intern("CLASS");
id_underscore = rb_intern("UNDERSCORE");
id_hyphen = rb_intern("HYPHEN");
id_space = rb_intern("SPACE");
- id_equal = rb_intern("=");
+ id_equal = rb_intern("EQUAL");
rb_const_set(rb_mAttributeBuilder, id_id, rb_obj_freeze(rb_str_new_cstr("id")));
rb_const_set(rb_mAttributeBuilder, id_class, rb_obj_freeze(rb_str_new_cstr("class")));
rb_const_set(rb_mAttributeBuilder, id_underscore, rb_obj_freeze(rb_str_new_cstr("_")));
rb_const_set(rb_mAttributeBuilder, id_hyphen, rb_obj_freeze(rb_str_new_cstr("-")));
rb_const_set(rb_mAttributeBuilder, id_space, rb_obj_freeze(rb_str_new_cstr(" ")));
rb_const_set(rb_mAttributeBuilder, id_equal, rb_obj_freeze(rb_str_new_cstr("=")));
-
- rb_require("temple");
}