Browse Source

[Minor] Merge OOM fixes from libucl

tags/1.9.3
Vsevolod Stakhov 5 years ago
parent
commit
24d852704f

+ 69
- 11
contrib/libucl/kvec.h View File

@@ -30,11 +30,13 @@
int main() {
kvec_t(int) array;
kv_init(array);
kv_push(int, array, 10); // append
kv_push_safe(int, array, 10, e0); // append
kv_a(int, array, 20) = 5; // dynamic
kv_A(array, 20) = 4; // static
kv_destroy(array);
return 0;
e0:
return 1;
}
*/

@@ -60,8 +62,71 @@ int main() {
#define kv_size(v) ((v).n)
#define kv_max(v) ((v).m)

#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
#define kv_resize_safe(type, v, s, el) do { \
type *_tp = (type*)realloc((v).a, sizeof(type) * (s)); \
if (_tp == NULL) { \
goto el; \
} else { \
(v).a = _tp; \
(v).m = (s); \
} \
} while (0)

#define kv_grow_factor 1.5
#define kv_grow_safe(type, v, el) do { \
size_t _ts = ((v).m > 1 ? (v).m * kv_grow_factor : 2); \
type *_tp = (type*)realloc((v).a, sizeof(type) * _ts); \
if (_tp == NULL) { \
goto el; \
} else { \
(v).a = _tp; \
(v).m = _ts; \
} \
} while (0)

#define kv_copy_safe(type, v1, v0, el) do { \
if ((v1).m < (v0).n) kv_resize_safe(type, v1, (v0).n, el); \
(v1).n = (v0).n; \
memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \
} while (0)

#define kv_push_safe(type, v, x, el) do { \
if ((v).n == (v).m) { \
kv_grow_safe(type, v, el); \
} \
(v).a[(v).n++] = (x); \
} while (0)

#define kv_prepend_safe(type, v, x, el) do { \
if ((v).n == (v).m) { \
kv_grow_safe(type, v, el); \
} \
memmove((v).a + 1, (v).a, sizeof(type) * (v).n); \
(v).a[0] = (x); \
(v).n ++; \
} while (0)

#define kv_concat_safe(type, v1, v0, el) do { \
if ((v1).m < (v0).n + (v1).n) \
kv_resize_safe(type, v1, (v0).n + (v1).n, el); \
memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n); \
(v1).n = (v0).n + (v1).n; \
} while (0)

#define kv_del(type, v, i) do { \
if ((i) < (v).n) { \
memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \
(v).n --; \
} \
} while (0)

/*
* Old (ENOMEM-unsafe) version of kv_xxx macros. Compat-only, not for use in
* the new library code.
*/

#define kv_resize(type, v, s) ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))

#define kv_grow(type, v) ((v).m = ((v).m > 1 ? (v).m * kv_grow_factor : 2), \
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m))

@@ -89,15 +154,8 @@ int main() {

#define kv_concat(type, v1, v0) do { \
if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n); \
memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * ((v0).n + (v1).n)); \
memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n); \
(v1).n = (v0).n + (v1).n; \
} while (0)

#define kv_del(type, v, i) do { \
if ((i) < (v).n) { \
memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \
(v).n --; \
} \
} while (0)

#endif
#endif /* AC_KVEC_H */

+ 20
- 5
contrib/libucl/ucl.h View File

@@ -469,8 +469,9 @@ UCL_EXTERN bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *e
* Reserve space in ucl array or object for `elt` elements
* @param obj object to reserve
* @param reserved size to reserve in an object
* @return 0 on success, -1 on failure (i.e. ENOMEM)
*/
UCL_EXTERN void ucl_object_reserve (ucl_object_t *obj, size_t reserved);
UCL_EXTERN bool ucl_object_reserve (ucl_object_t *obj, size_t reserved);

/**
* Append an element to the end of array object
@@ -825,11 +826,14 @@ typedef void* ucl_object_iter_t;
* @param iter opaque iterator, must be set to NULL on the first call:
* ucl_object_iter_t it = NULL;
* while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
* @param ep pointer record exception (such as ENOMEM), could be NULL
* @return the next object or NULL
*/
UCL_EXTERN const ucl_object_t* ucl_object_iterate (const ucl_object_t *obj,
ucl_object_iter_t *iter, bool expand_values);
UCL_EXTERN const ucl_object_t* ucl_object_iterate_with_error (const ucl_object_t *obj,
ucl_object_iter_t *iter, bool expand_values, int *ep);

#define ucl_iterate_object ucl_object_iterate
#define ucl_object_iterate(ob, it, ev) ucl_object_iterate_with_error((ob), (it), (ev), NULL)

/**
* Create new safe iterator for the specified object
@@ -838,6 +842,15 @@ UCL_EXTERN const ucl_object_t* ucl_object_iterate (const ucl_object_t *obj,
*/
UCL_EXTERN ucl_object_iter_t ucl_object_iterate_new (const ucl_object_t *obj)
UCL_WARN_UNUSED_RESULT;
/**
* Check safe iterator object after performing some operations on it
* (such as ucl_object_iterate_safe()) to see if operation has encountered
* fatal exception while performing that operation (e.g. ENOMEM).
* @param iter opaque iterator
* @return true if exception has occured, false otherwise
*/
UCL_EXTERN bool ucl_object_iter_chk_excpn(ucl_object_iter_t *it);

/**
* Reset initialized iterator to a new object
* @param obj new object to iterate
@@ -951,8 +964,9 @@ UCL_EXTERN int ucl_parser_get_default_priority (struct ucl_parser *parser);
* @param macro macro name (without leading dot)
* @param handler handler (it is called immediately after macro is parsed)
* @param ud opaque user data for a handler
* @return true on success, false on failure (i.e. ENOMEM)
*/
UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
UCL_EXTERN bool ucl_parser_register_macro (struct ucl_parser *parser,
const char *macro,
ucl_macro_handler handler, void* ud);

@@ -962,8 +976,9 @@ UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser,
* @param macro macro name (without leading dot)
* @param handler handler (it is called immediately after macro is parsed)
* @param ud opaque user data for a handler
* @return true on success, false on failure (i.e. ENOMEM)
*/
UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser,
UCL_EXTERN bool ucl_parser_register_context_macro (struct ucl_parser *parser,
const char *macro,
ucl_context_macro_handler handler,
void* ud);

+ 38
- 20
contrib/libucl/ucl_hash.c View File

@@ -147,17 +147,21 @@ ucl_hash_create (bool ignore_case)

new = UCL_ALLOC (sizeof (ucl_hash_t));
if (new != NULL) {
void *h;
kv_init (new->ar);

new->caseless = ignore_case;
if (ignore_case) {
khash_t(ucl_hash_caseless_node) *h = kh_init (ucl_hash_caseless_node);
new->hash = (void *)h;
h = (void *)kh_init (ucl_hash_caseless_node);
}
else {
khash_t(ucl_hash_node) *h = kh_init (ucl_hash_node);
new->hash = (void *)h;
h = (void *)kh_init (ucl_hash_node);
}
if (h == NULL) {
UCL_FREE (sizeof (ucl_hash_t), new);
return NULL;
}
new->hash = h;
}
return new;
}
@@ -190,12 +194,12 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)

if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
hashlin->hash;
kh_destroy (ucl_hash_caseless_node, h);
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
hashlin->hash;
kh_destroy (ucl_hash_node, h);
}

@@ -203,16 +207,16 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
UCL_FREE (sizeof (*hashlin), hashlin);
}

void
bool
ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
const char *key, unsigned keylen)
const char *key, unsigned keylen)
{
khiter_t k;
int ret;
struct ucl_hash_elt *elt;

if (hashlin == NULL) {
return;
return false;
}

if (hashlin->caseless) {
@@ -221,7 +225,7 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
if (ret > 0) {
elt = &kh_value (h, k);
kv_push (const ucl_object_t *, hashlin->ar, obj);
kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
elt->obj = obj;
elt->ar_idx = kv_size (hashlin->ar) - 1;
}
@@ -232,15 +236,20 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
k = kh_put (ucl_hash_node, h, obj, &ret);
if (ret > 0) {
elt = &kh_value (h, k);
kv_push (const ucl_object_t *, hashlin->ar, obj);
kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
elt->obj = obj;
elt->ar_idx = kv_size (hashlin->ar) - 1;
} else if (ret < 0) {
goto e0;
}
}
return true;
e0:
return false;
}

void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
const ucl_object_t *new)
const ucl_object_t *new)
{
khiter_t k;
int ret;
@@ -285,13 +294,16 @@ struct ucl_hash_real_iter {
const ucl_object_t **end;
};

#define UHI_SETERR(ep, ern) {if (ep != NULL) *ep = (ern);}

const void*
ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
{
struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(*iter);
const ucl_object_t *ret = NULL;

if (hashlin == NULL) {
UHI_SETERR(ep, EINVAL);
return NULL;
}

@@ -299,6 +311,7 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
it = UCL_ALLOC (sizeof (*it));

if (it == NULL) {
UHI_SETERR(ep, ENOMEM);
return NULL;
}

@@ -306,6 +319,7 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
it->end = it->cur + hashlin->ar.n;
}

UHI_SETERR(ep, 0);
if (it->cur < it->end) {
ret = *it->cur++;
}
@@ -346,7 +360,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)

if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
hashlin->hash;

k = kh_get (ucl_hash_caseless_node, h, &search);
if (k != kh_end (h)) {
@@ -356,7 +370,7 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen)
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
hashlin->hash;
k = kh_get (ucl_hash_node, h, &search);
if (k != kh_end (h)) {
elt = &kh_value (h, k);
@@ -380,7 +394,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)

if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(ucl_hash_caseless_node) *)
hashlin->hash;
hashlin->hash;

k = kh_get (ucl_hash_caseless_node, h, obj);
if (k != kh_end (h)) {
@@ -398,7 +412,7 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
}
else {
khash_t(ucl_hash_node) *h = (khash_t(ucl_hash_node) *)
hashlin->hash;
hashlin->hash;
k = kh_get (ucl_hash_node, h, obj);
if (k != kh_end (h)) {
elt = &kh_value (h, k);
@@ -415,14 +429,15 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
}
}

void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
bool
ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
{
if (hashlin == NULL) {
return;
return false;
}

if (sz > hashlin->ar.m) {
kv_resize (const ucl_object_t *, hashlin->ar, sz);
kv_resize_safe (const ucl_object_t *, hashlin->ar, sz, e0);

if (hashlin->caseless) {
khash_t(ucl_hash_caseless_node) *h = (khash_t(
@@ -435,4 +450,7 @@ void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
kh_resize (ucl_hash_node, h, sz * 2);
}
}
return true;
e0:
return false;
}

+ 11
- 3
contrib/libucl/ucl_hash.h View File

@@ -55,8 +55,9 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func);

/**
* Inserts an element in the the hashtable.
* @return true on success, false on failure (i.e. ENOMEM)
*/
void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
bool ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key,
unsigned keylen);

/**
@@ -81,9 +82,15 @@ const ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key,
* Iterate over hash table
* @param hashlin hash
* @param iter iterator (must be NULL on first iteration)
* @param ep pointer record exception (such as ENOMEM), could be NULL
* @return the next object
*/
const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter);
const void* ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep);

/**
* Helper macro to support older code
*/
#define ucl_hash_iterate(hl, ip) ucl_hash_iterate2((hl), (ip), NULL)

/**
* Check whether an iterator has next element
@@ -92,8 +99,9 @@ bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter);

/**
* Reserves space in hash
* @return true on sucess, false on failure (e.g. ENOMEM)
* @param hashlin
*/
void ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);
bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);

#endif

+ 15
- 3
contrib/libucl/ucl_internal.h View File

@@ -472,12 +472,24 @@ ucl_hash_insert_object (ucl_hash_t *hashlin,
const ucl_object_t *obj,
bool ignore_case)
{
ucl_hash_t *nhp;

if (hashlin == NULL) {
hashlin = ucl_hash_create (ignore_case);
nhp = ucl_hash_create (ignore_case);
if (nhp == NULL) {
return NULL;
}
} else {
nhp = hashlin;
}
if (!ucl_hash_insert (nhp, obj, obj->key, obj->keylen)) {
if (nhp != hashlin) {
ucl_hash_destroy(nhp, NULL);
}
return NULL;
}
ucl_hash_insert (hashlin, obj, obj->key, obj->keylen);

return hashlin;
return nhp;
}

/**

+ 69
- 57
contrib/libucl/ucl_parser.c View File

@@ -634,70 +634,51 @@ ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
bool is_array, uint32_t level, bool has_obrace)
{
struct ucl_stack *st;
bool need_free = false;

if (!is_array) {
if (obj == NULL) {
obj = ucl_object_new_full (UCL_OBJECT, parser->chunks->priority);
need_free = true;
}
else {
if (obj->type == UCL_ARRAY) {
/* Bad combination for merge: array and object */
ucl_set_err (parser, UCL_EMERGE,
"cannot merge an array with an object",
&parser->err);

return NULL;
}
ucl_object_t *nobj;

obj->type = UCL_OBJECT;
if (obj == NULL) {
nobj = ucl_object_new_full (is_array ? UCL_ARRAY : UCL_OBJECT, parser->chunks->priority);
if (nobj == NULL) {
goto enomem0;
}
} else {
if (obj->type == (is_array ? UCL_OBJECT : UCL_ARRAY)) {
/* Bad combination for merge: array and object */
ucl_set_err (parser, UCL_EMERGE,
"cannot merge an object with an array",
&parser->err);

if (obj->value.ov == NULL) {
obj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE);
return NULL;
}
parser->state = UCL_STATE_KEY;
nobj = obj;
nobj->type = is_array ? UCL_ARRAY : UCL_OBJECT;
}
else {
if (obj == NULL) {
obj = ucl_object_new_full (UCL_ARRAY, parser->chunks->priority);
need_free = true;
}
else {
if (obj->type == UCL_OBJECT) {
/* Bad combination for merge: array and object */
ucl_set_err (parser, UCL_EMERGE,
"cannot merge an object with an array",
&parser->err);

return NULL;
if (!is_array) {
if (nobj->value.ov == NULL) {
nobj->value.ov = ucl_hash_create (parser->flags & UCL_PARSER_KEY_LOWERCASE);
if (nobj->value.ov == NULL) {
goto enomem1;
}

obj->type = UCL_ARRAY;
}
parser->state = UCL_STATE_KEY;
} else {
parser->state = UCL_STATE_VALUE;
}

st = UCL_ALLOC (sizeof (struct ucl_stack));

if (st == NULL) {
ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
&parser->err);
if (need_free) {
ucl_object_unref (obj);
}

return NULL;
goto enomem1;
}

st->obj = obj;
st->obj = nobj;

if (level >= UINT16_MAX) {
ucl_set_err (parser, UCL_ENESTED,
"objects are nesting too deep (over 65535 limit)",
&parser->err);
if (need_free) {
if (nobj != obj) {
ucl_object_unref (obj);
}

@@ -717,9 +698,16 @@ ucl_parser_add_container (ucl_object_t *obj, struct ucl_parser *parser,
}

LL_PREPEND (parser->stack, st);
parser->cur_obj = obj;
parser->cur_obj = nobj;

return obj;
return nobj;
enomem1:
if (nobj != obj)
ucl_object_unref (nobj);
enomem0:
ucl_set_err (parser, UCL_EINTERNAL, "cannot allocate memory for an object",
&parser->err);
return NULL;
}

int
@@ -1194,6 +1182,9 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
if (tobj == NULL) {
container = ucl_hash_insert_object (container, nobj,
parser->flags & UCL_PARSER_KEY_LOWERCASE);
if (container == NULL) {
return false;
}
nobj->prev = nobj;
nobj->next = NULL;
parser->stack->obj->len ++;
@@ -1477,6 +1468,9 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk,

/* Create a new object */
nobj = ucl_object_new_full (UCL_NULL, parser->chunks->priority);
if (nobj == NULL) {
return false;
}
keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY],
&key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE,
false, false);
@@ -2672,6 +2666,11 @@ ucl_state_machine (struct ucl_parser *parser)
return true;
}

#define UPRM_SAFE(fn, a, b, c, el) do { \
if (!fn(a, b, c, a)) \
goto el; \
} while (0)

struct ucl_parser*
ucl_parser_new (int flags)
{
@@ -2684,12 +2683,12 @@ ucl_parser_new (int flags)

memset (parser, 0, sizeof (struct ucl_parser));

ucl_parser_register_macro (parser, "include", ucl_include_handler, parser);
ucl_parser_register_macro (parser, "try_include", ucl_try_include_handler, parser);
ucl_parser_register_macro (parser, "includes", ucl_includes_handler, parser);
ucl_parser_register_macro (parser, "priority", ucl_priority_handler, parser);
ucl_parser_register_macro (parser, "load", ucl_load_handler, parser);
ucl_parser_register_context_macro (parser, "inherit", ucl_inherit_handler, parser);
UPRM_SAFE(ucl_parser_register_macro, parser, "include", ucl_include_handler, e0);
UPRM_SAFE(ucl_parser_register_macro, parser, "try_include", ucl_try_include_handler, e0);
UPRM_SAFE(ucl_parser_register_macro, parser, "includes", ucl_includes_handler, e0);
UPRM_SAFE(ucl_parser_register_macro, parser, "priority", ucl_priority_handler, e0);
UPRM_SAFE(ucl_parser_register_macro, parser, "load", ucl_load_handler, e0);
UPRM_SAFE(ucl_parser_register_context_macro, parser, "inherit", ucl_inherit_handler, e0);

parser->flags = flags;
parser->includepaths = NULL;
@@ -2704,6 +2703,9 @@ ucl_parser_new (int flags)
}

return parser;
e0:
ucl_parser_free(parser);
return NULL;
}

bool
@@ -2728,49 +2730,59 @@ ucl_parser_get_default_priority (struct ucl_parser *parser)
return parser->default_priority;
}

void
bool
ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
ucl_macro_handler handler, void* ud)
{
struct ucl_macro *new;

if (macro == NULL || handler == NULL) {
return;
return false;
}

new = UCL_ALLOC (sizeof (struct ucl_macro));
if (new == NULL) {
return;
return false;
}

memset (new, 0, sizeof (struct ucl_macro));
new->h.handler = handler;
new->name = strdup (macro);
if (new->name == NULL) {
UCL_FREE (sizeof (struct ucl_macro), new);
return false;
}
new->ud = ud;
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
return true;
}

void
bool
ucl_parser_register_context_macro (struct ucl_parser *parser, const char *macro,
ucl_context_macro_handler handler, void* ud)
{
struct ucl_macro *new;

if (macro == NULL || handler == NULL) {
return;
return false;
}

new = UCL_ALLOC (sizeof (struct ucl_macro));
if (new == NULL) {
return;
return false;
}

memset (new, 0, sizeof (struct ucl_macro));
new->h.context_handler = handler;
new->name = strdup (macro);
if (new->name == NULL) {
UCL_FREE (sizeof (struct ucl_macro), new);
return false;
}
new->ud = ud;
new->is_context = true;
HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new);
return true;
}

void

+ 37
- 11
contrib/libucl/ucl_util.c View File

@@ -2688,7 +2688,8 @@ ucl_object_lookup_any (const ucl_object_t *obj,
}

const ucl_object_t*
ucl_object_iterate (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
ucl_object_iterate_with_error (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values,
int *ep)
{
const ucl_object_t *elt = NULL;

@@ -2699,7 +2700,7 @@ ucl_object_iterate (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expan
if (expand_values) {
switch (obj->type) {
case UCL_OBJECT:
return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
return (const ucl_object_t*)ucl_hash_iterate2 (obj->value.ov, iter, ep);
break;
case UCL_ARRAY: {
unsigned int idx;
@@ -2745,6 +2746,7 @@ enum ucl_safe_iter_flags {
UCL_ITERATE_FLAG_INSIDE_ARRAY,
UCL_ITERATE_FLAG_INSIDE_OBJECT,
UCL_ITERATE_FLAG_IMPLICIT,
UCL_ITERATE_FLAG_EXCEPTION
};

const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
@@ -2777,6 +2779,15 @@ ucl_object_iterate_new (const ucl_object_t *obj)
return (ucl_object_iter_t)it;
}

bool
ucl_object_iter_chk_excpn(ucl_object_iter_t *it)
{
struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);

UCL_SAFE_ITER_CHECK (rit);

return (rit->flags == UCL_ITERATE_FLAG_EXCEPTION);
}

ucl_object_iter_t
ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
@@ -2810,6 +2821,7 @@ ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
{
struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
const ucl_object_t *ret = NULL;
int ern;

UCL_SAFE_ITER_CHECK (rit);

@@ -2819,7 +2831,12 @@ ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)

if (rit->impl_it->type == UCL_OBJECT) {
rit->flags = UCL_ITERATE_FLAG_INSIDE_OBJECT;
ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
ret = ucl_object_iterate_with_error (rit->impl_it, &rit->expl_it, true, &ern);

if (ret == NULL && ern != 0) {
rit->flags = UCL_ITERATE_FLAG_EXCEPTION;
return NULL;
}

if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
/* Need to switch to another implicit object in chain */
@@ -2967,7 +2984,7 @@ ucl_object_new_full (ucl_type_t type, unsigned priority)
UCL_ARRAY_GET (vec, new);

/* Preallocate some space for arrays */
kv_resize (ucl_object_t *, *vec, 8);
kv_resize_safe (ucl_object_t *, *vec, 8, enomem);
}
}
}
@@ -2976,23 +2993,26 @@ ucl_object_new_full (ucl_type_t type, unsigned priority)
new = ucl_object_new_userdata (NULL, NULL, NULL);
ucl_object_set_priority (new, priority);
}
enomem:
return new;
}

void ucl_object_reserve (ucl_object_t *obj, size_t reserved)
bool ucl_object_reserve (ucl_object_t *obj, size_t reserved)
{
if (obj->type == UCL_ARRAY) {
UCL_ARRAY_GET (vec, obj);

if (vec->m < reserved) {
/* Preallocate some space for arrays */
kv_resize (ucl_object_t *, *vec, reserved);
kv_resize_safe (ucl_object_t *, *vec, reserved, e0);
}
}
else if (obj->type == UCL_OBJECT) {
ucl_hash_reserve (obj->value.ov, reserved);
}
return true;
e0:
return false;
}

ucl_object_t*
@@ -3102,11 +3122,13 @@ ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
top->value.av = (void *)vec;
}

kv_push (ucl_object_t *, *vec, elt);
kv_push_safe (ucl_object_t *, *vec, elt, e0);

top->len ++;

return true;
e0:
return false;
}

bool
@@ -3122,16 +3144,18 @@ ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
vec = UCL_ALLOC (sizeof (*vec));
kv_init (*vec);
top->value.av = (void *)vec;
kv_push (ucl_object_t *, *vec, elt);
kv_push_safe (ucl_object_t *, *vec, elt, e0);
}
else {
/* Slow O(n) algorithm */
kv_prepend (ucl_object_t *, *vec, elt);
kv_prepend_safe (ucl_object_t *, *vec, elt, e0);
}

top->len ++;

return true;
e0:
return false;
}

bool
@@ -3156,7 +3180,7 @@ ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
UCL_ARRAY_GET (v2, cp);

if (v1 && v2) {
kv_concat (ucl_object_t *, *v1, *v2);
kv_concat_safe (ucl_object_t *, *v1, *v2, e0);

for (i = v2->n; i < v1->n; i ++) {
obj = &kv_A (*v1, i);
@@ -3168,6 +3192,8 @@ ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
}

return true;
e0:
return false;
}

ucl_object_t *

Loading…
Cancel
Save