ext/i18nema/i18nema.c in i18nema-0.0.5 vs ext/i18nema/i18nema.c in i18nema-0.0.6
- old
+ new
@@ -1,10 +1,12 @@
#include <ruby.h>
#include <ruby/encoding.h>
#include "vendor/syck.h"
#include "vendor/uthash.h"
+#define CAN_FREE(item) item != NULL && item->type != i_type_true && item->type != i_type_false && item->type != i_type_null
+
VALUE I18nema = Qnil,
I18nemaBackend = Qnil,
I18nemaBackendLoadError = Qnil;
struct i_object;
@@ -16,11 +18,11 @@
static void delete_object(struct i_object *object, int recurse);
static void delete_object_r(struct i_object *object);
static VALUE normalize_key(VALUE self, VALUE key, VALUE separator);
enum i_object_type {
- i_type_none,
+ i_type_unused,
i_type_string,
i_type_array,
i_type_hash,
i_type_int,
i_type_float,
@@ -30,11 +32,11 @@
i_type_null
};
union i_object_data {
char *string;
- struct i_object **array;
+ struct i_object *array;
struct i_key_value *hash;
};
typedef struct i_object
{
@@ -90,11 +92,11 @@
static VALUE
array_to_rarray(i_object_t *array)
{
VALUE result = rb_ary_new2(array->size);
for (unsigned long i = 0; i < array->size; i++)
- rb_ary_store(result, i, i_object_to_robject(array->data.array[i]));
+ rb_ary_store(result, i, i_object_to_robject(&array->data.array[i]));
return result;
}
static VALUE
hash_to_rhash(i_object_t *hash)
@@ -165,17 +167,17 @@
switch (object->type) {
case i_type_array:
if (recurse)
for (unsigned long i = 0; i < object->size; i++)
- delete_object_r(object->data.array[i]);
+ empty_object(&object->data.array[i], 1);
xfree(object->data.array);
break;
case i_type_hash:
delete_hash(&object->data.hash, recurse);
break;
- case i_type_none:
+ case i_type_unused:
break;
default:
xfree(object->data.string);
break;
}
@@ -183,11 +185,11 @@
static void
delete_object(i_object_t *object, int recurse)
{
empty_object(object, recurse);
- if (object->type != i_type_null && object->type != i_type_true && object->type != i_type_false)
+ if (CAN_FREE(object))
xfree(object);
}
static void
delete_object_r(i_object_t *object)
@@ -246,12 +248,13 @@
static int
delete_syck_st_entry(char *key, char *value, char *arg)
{
i_object_t *object = (i_object_t *)value;
- // key object whose string we have yoinked into a kv
- if (object->type == i_type_none)
+ // key object whose string we have yoinked into a kv, or item that
+ // has been copied into an array
+ if (object->type == i_type_unused)
delete_object_r(object);
return ST_DELETE;
}
static int
@@ -291,27 +294,33 @@
strncpy(str, orig, len);
str[len] = '\0';
return str;
}
-static i_object_t*
-new_string_object(char *str, long len)
+static void
+set_string_object(i_object_t *object, char *str, long len)
{
- i_object_t *object = ALLOC(i_object_t);
object->type = i_type_string;
object->size = len;
object->data.string = new_string(str, len);
+}
+
+static i_object_t*
+new_string_object(char *str, long len)
+{
+ i_object_t *object = ALLOC(i_object_t);
+ set_string_object(object, str, len);
return object;
}
static i_object_t*
new_array_object(long size)
{
i_object_t *object = ALLOC(i_object_t);
object->type = i_type_array;
object->size = size;
- object->data.array = ALLOC_N(i_object_t*, size);
+ object->data.array = ALLOC_N(i_object_t, size);
return object;
}
static i_object_t*
new_hash_object()
@@ -370,11 +379,13 @@
oid = syck_seq_read(node, i);
syck_lookup_sym(parser, oid, (void **)&item);
if (item->type == i_type_string)
current_translation_count++;
- result->data.array[i] = item;
+ memcpy(&result->data.array[i], item, sizeof(i_object_t));
+ if (CAN_FREE(item))
+ item->type = i_type_unused;
}
break;
case syck_map_kind:
result = new_hash_object();
for (long i = 0; i < node->data.pairs->idx; i++) {
@@ -384,11 +395,11 @@
syck_lookup_sym(parser, oid, (void **)&key);
oid = syck_map_read(node, map_value, i);
syck_lookup_sym(parser, oid, (void **)&value);
i_key_value_t *kv = new_key_value(key->data.string, value);
- key->type = i_type_none; // so we know to free this node in delete_syck_st_entry
+ key->type = i_type_unused; // so we know to free this node in delete_syck_st_entry
if (value->type == i_type_string)
current_translation_count++;
add_key_value(&result->data.hash, kv);
}
break;
@@ -536,10 +547,10 @@
VALUE part = RARRAY_PTR(parts)[i];
// TODO: don't alloc for empty strings, since we discard them
if (RSTRING_LEN(part) == 0)
skipped++;
else
- key_frd->data.array[i - skipped] = new_string_object(RSTRING_PTR(part), RSTRING_LEN(part));
+ set_string_object(&key_frd->data.array[i - skipped], RSTRING_PTR(part), RSTRING_LEN(part));
}
key_frd->size -= skipped;
char *key_orig = new_string(RSTRING_PTR(key), RSTRING_LEN(key));
i_key_value_t *kv = new_key_value(key_orig, key_frd);