/* Replace element in the array */ int ref_array_replace(struct ref_array *ra, uint32_t idx, void *element) { int error = EOK; TRACE_FLOW_ENTRY(); if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if (idx > ra->len) { TRACE_ERROR_NUMBER("Index is out of range", ERANGE); return ERANGE; } /* Clear old element */ if (ra->cb) ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize, REF_ARRAY_DELETE, ra->cb_data); /* Overwrite element */ memcpy((unsigned char *)(ra->storage) + idx * ra->elsize, element, ra->elsize); TRACE_FLOW_EXIT(); return error; }
/* Change boundary */ int value_set_boundary(struct value_obj *vo, uint32_t boundary) { int error = EOK; TRACE_FLOW_ENTRY(); if (!vo) { TRACE_ERROR_NUMBER("Invalid object", EINVAL); return EINVAL; } vo->boundary = boundary; /* Fold in new value */ error = value_fold(vo->unfolded, vo->keylen, vo->boundary, vo->raw_lines, vo->raw_lengths); if (error) { TRACE_ERROR_NUMBER("Failed to fold", error); /* In this case nothing to free here but * the object might be unusable */ return error; } TRACE_FLOW_EXIT(); return EOK; }
/* Remove element from the array */ int ref_array_remove(struct ref_array *ra, uint32_t idx) { int error = EOK; uint32_t i; TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if (idx >= ra->len) { TRACE_ERROR_NUMBER("Index is out of range", ERANGE); return ERANGE; } /* Clear old element */ if (ra->cb) ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize, REF_ARRAY_DELETE, ra->cb_data); /* Shift elements left */ for (i = idx + 1; i < ra->len; i++) { memcpy((unsigned char *)(ra->storage) + (i - 1) * ra->elsize, (unsigned char *)(ra->storage) + i * ra->elsize, ra->elsize); } ra->len--; TRACE_FLOW_EXIT(); return error; }
/* Add a raw string to the arrays */ int value_add_to_arrays(const char *strvalue, uint32_t len, struct ref_array *raw_lines, struct ref_array *raw_lengths) { int error = EOK; TRACE_FLOW_ENTRY(); error = ref_array_append(raw_lines, (void *)(&strvalue)); if (error) { TRACE_ERROR_NUMBER("Failed to add to lines array", error); return error; } error = ref_array_append(raw_lengths, (void *)(&len)); if (error) { TRACE_ERROR_NUMBER("Failed to add to lengths array", error); return error; } TRACE_FLOW_EXIT(); return error; }
/* Set the folding boundary for multiline values. * Use before serializing and saving to a file if the * default boundary of 80 characters does not work for you. */ int ini_config_set_wrap(struct ini_cfgobj *ini_config, uint32_t boundary) { int error = EOK; TRACE_FLOW_ENTRY(); if (!ini_config) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } ini_config->boundary = boundary; error = col_traverse_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT, ini_boundary_cb, (void *)(&(ini_config->boundary))); if (error) { TRACE_ERROR_NUMBER("Failed to set wrapping boundary", error); return error; } TRACE_FLOW_EXIT(); return error; }
/* Add new element to the array */ int ref_array_append(struct ref_array *ra, void *element) { int error = EOK; TRACE_FLOW_ENTRY(); if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } /* Do we have enough room for a new element? */ if (ra->size == ra->len) { error = ref_array_grow(ra); if (error) { TRACE_ERROR_NUMBER("Failed to grow array.", error); return error; } } /* Copy element */ memcpy((unsigned char *)(ra->storage) + ra->len * ra->elsize, element, ra->elsize); ra->len++; TRACE_INFO_NUMBER("Length after append: ", ra->len); TRACE_FLOW_EXIT(); return error; }
static int save_portion(struct ref_array *raw_lines, struct ref_array *raw_lengths, const char* buf, uint32_t len) { int error = EOK; char *copy = NULL; uint32_t adj = 0; TRACE_FLOW_ENTRY(); /* Add leading space only if there is * a) no space * b) it is not an empty line * c) it is now a first line */ if ((buf[0] != ' ') && (buf[0] != '\t') && (len != 0) && (ref_array_len(raw_lines) != 0)) adj = 1; copy = malloc(len + adj + 1); if (!copy) { TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM); return ENOMEM; } memcpy(copy + adj, buf, len); len += adj; copy[len] = 0; /* If the section being saved is not starting * with space add a space. */ if (adj) copy[0] = ' '; error = ref_array_append(raw_lines, (void *)(©)); if (error) { TRACE_ERROR_NUMBER("Failed to append line", error); free(copy); return error; } error = ref_array_append(raw_lengths, (void *)(&len)); if (error) { TRACE_ERROR_NUMBER("Failed to append length", error); return error; } TRACE_INFO_STRING("Added string:", (char *)copy); TRACE_INFO_NUMBER("Added number:", len); TRACE_FLOW_EXIT(); return EOK; }
/* Print the collection using iterator */ int col_print_collection2(struct collection_item *handle) { struct collection_iterator *iterator = NULL; int error = EOK; struct collection_item *item = NULL; int nest_level = 0; int dummy = 0; int line = 1; TRACE_FLOW_STRING("col_print_collection2", "Entry"); /* If we have something to print print it */ if (handle == NULL) { TRACE_ERROR_STRING("No error list", ""); return EINVAL; } /* Bind iterator */ error = col_bind_iterator(&iterator, handle, COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END | COL_TRAVERSE_SHOWSUB); if (error) { TRACE_ERROR_NUMBER("Error (bind):", error); return error; } do { /* Loop through a collection */ error = col_iterate_collection(iterator, &item); if (error) { TRACE_ERROR_NUMBER("Error (iterate):", error); col_unbind_iterator(iterator); return error; } /* Are we done ? */ if (item == NULL) break; if (item->type != COL_TYPE_END) printf("%05d", line); col_debug_handle(item->property, item->property_len, item->type, item->data, item->length, (void *)(&nest_level), &dummy); line++; } while(1); /* Do not forget to unbind iterator - otherwise there will be a leak */ col_unbind_iterator(iterator); TRACE_INFO_STRING("col_print_collection2", "Exit"); return EOK; }
/* Inspect the line */ static int parser_inspect(struct parser_obj *po) { int error = EOK; uint32_t action = PARSE_DONE; TRACE_FLOW_ENTRY(); TRACE_INFO_STRING("Buffer:", po->last_read); TRACE_INFO_NUMBER("In comment:", po->inside_comment); if (check_for_comment(po->last_read, po->last_read_len, !(po->parse_flags & INI_PARSE_NO_C_COMMENTS), &(po->inside_comment))) { error = handle_comment(po, &action); if (error) { TRACE_ERROR_NUMBER("Failed to process comment", error); return error; } } else if (isspace(*(po->last_read))) { error = handle_space(po, &action); if (error) { TRACE_ERROR_NUMBER("Failed to process line wrapping", error); return error; } } else if (*(po->last_read) == '[') { error = handle_section(po, &action); if (error) { TRACE_ERROR_NUMBER("Failed to save section", error); return error; } } else { error = handle_kvp(po, &action); if (error) { TRACE_ERROR_NUMBER("Failed to save kvp", error); return error; } } /* Move to the next action */ error = col_enqueue_unsigned_property(po->queue, PARSE_ACTION, action); if (error) { TRACE_ERROR_NUMBER("Failed to schedule an action", error); return error; } TRACE_FLOW_EXIT(); return error; }
/* Complete file processing */ static int parser_post(struct parser_obj *po) { int error = EOK; TRACE_FLOW_ENTRY(); /* If there was just a comment at the bottom * put it directly into the config object */ if((po->ic) && (!(po->key))) { if (po->co->last_comment) { error = ini_comment_add(po->ic, po->co->last_comment); if (error) { TRACE_ERROR_NUMBER("Failed to merge comment", error); return error; } } else { error = ini_comment_copy(po->ic, &(po->co->last_comment)); if (error) { TRACE_ERROR_NUMBER("Failed to copy comment", error); return error; } } ini_comment_destroy(po->ic); po->ic = NULL; } /* If there is a key being processed add it */ if (po->key) { error = complete_value_processing(po); if (error) { TRACE_ERROR_NUMBER("Failed to complete value processing", error); return error; } } /* If we are done save the section */ error = parser_save_section(po); if (error) { TRACE_ERROR_NUMBER("Failed to save section", error); return error; } /* Move to the next action */ error = col_enqueue_unsigned_property(po->queue, PARSE_ACTION, PARSE_DONE); if (error) { TRACE_ERROR_NUMBER("Failed to schedule an action", error); return error; } TRACE_FLOW_EXIT(); return EOK; }
/* Create value from a referenced array */ int value_create_from_refarray(struct ref_array *raw_lines, struct ref_array *raw_lengths, uint32_t line, uint32_t origin, uint32_t key_len, uint32_t boundary, struct ini_comment *ic, struct value_obj **vo) { int error = EOK; struct value_obj *new_vo = NULL; TRACE_FLOW_ENTRY(); if ((!raw_lines) || (!raw_lengths) || (!vo)) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } new_vo = malloc(sizeof(struct value_obj)); if (!new_vo) { TRACE_ERROR_NUMBER("No memory", ENOMEM); return ENOMEM; } /* We are not using references here since * it will be inconsistent with the way * how comment is handled. * We could have added references here and make * comment keep references but it seems to be * and overhead in this case. */ new_vo->raw_lines = raw_lines; new_vo->raw_lengths = raw_lengths; new_vo->origin = origin; new_vo->line = line; new_vo->keylen = key_len; new_vo->boundary = boundary; new_vo->ic = ic; error = value_unfold(new_vo->raw_lines, new_vo->raw_lengths, &(new_vo->unfolded)); if (error) { TRACE_ERROR_NUMBER("Failed to unfold", error); value_destroy(new_vo); return error; } TRACE_INFO_STRING("Unfolded:", (const char *)simplebuffer_get_buf(new_vo->unfolded)); *vo = new_vo; TRACE_FLOW_EXIT(); return error; }
/* Update value */ int value_update(struct value_obj *vo, const char *value, uint32_t length, uint32_t origin, uint32_t boundary) { int error = EOK; struct simplebuffer *oneline = NULL; if ((!value) || (!vo)) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } /* Create buffer to hold the value */ error = simplebuffer_alloc(&oneline); if (error) { TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error); return error; } /* Put value into the buffer */ error = simplebuffer_add_str(oneline, value, length, INI_VALUE_BLOCK); if (error) { TRACE_ERROR_NUMBER("Failed to add string", error); simplebuffer_free(oneline); return error; } simplebuffer_free(vo->unfolded); vo->origin = origin; vo->unfolded = oneline; vo->boundary = boundary; /* Fold in new value */ error = value_fold(vo->unfolded, vo->keylen, vo->boundary, vo->raw_lines, vo->raw_lengths); if (error) { TRACE_ERROR_NUMBER("Failed to fold", error); /* In this case nothing to free here but * the object might be unsiable */ return error; } TRACE_FLOW_EXIT(); return error; }
/* Run parser */ static int parser_run(struct parser_obj *po) { int error = EOK; struct collection_item *item = NULL; uint32_t action = 0; action_fn operations[] = { parser_read, parser_inspect, parser_post, parser_error, NULL }; TRACE_FLOW_ENTRY(); while(1) { /* Get next action */ item = NULL; error = col_dequeue_item(po->queue, &item); if (error) { TRACE_ERROR_NUMBER("Failed to get action", error); return error; } /* Get action, run operation */ action = *((uint32_t *)(col_get_item_data(item))); col_delete_item(item); if (action == PARSE_DONE) { TRACE_INFO_NUMBER("We are done", error); /* Report merge error in detect mode * if no other error was detected. */ if ((po->ret == 0) && (po->merge_error != 0) && ((po->collision_flags & INI_MV1S_DETECT) || (po->collision_flags & INI_MV2S_DETECT) || (po->collision_flags & INI_MS_DETECT))) po->ret = po->merge_error; error = po->ret; break; } error = operations[action](po); if (error) { TRACE_ERROR_NUMBER("Failed to perform an action", error); return error; } } TRACE_FLOW_EXIT(); return error; }
/* Unfold the value represented by the array */ static int value_unfold(struct ref_array *raw_lines, struct ref_array *raw_lengths, struct simplebuffer **unfolded) { int error; struct simplebuffer *oneline = NULL; uint32_t len = 0; char *ptr = NULL; uint32_t i = 0; char *part = NULL; TRACE_FLOW_ENTRY(); error = simplebuffer_alloc(&oneline); if (error) { TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error); return error; } for (;;) { /* Get line */ ptr = ref_array_get(raw_lines, i, NULL); if (ptr) { /* Get its length */ ref_array_get(raw_lengths, i, (void *)&len); part = *((char **)(ptr)); TRACE_INFO_STRING("Value:", part); TRACE_INFO_NUMBER("Lenght:", len); error = simplebuffer_add_raw(oneline, part, len, INI_VALUE_BLOCK); if (error) { TRACE_ERROR_NUMBER("Failed to add string", error); simplebuffer_free(oneline); return error; } i++; } else break; } *unfolded = oneline; TRACE_FLOW_EXIT(); return error; }
/* Prepare metadata */ int prepare_metadata(uint32_t metaflags, struct collection_item **metadata, int *save_error) { int error = EOK; struct collection_item *metasec = NULL; TRACE_FLOW_STRING("prepare_metadata", "Entry"); /* Are we supposed to collect or process meta data ? */ if (!metadata) { TRACE_FLOW_STRING("No meta data", "Exit"); return EOK; } /* Allocate metadata */ error = col_create_collection(metadata, INI_METADATA, COL_CLASS_INI_META); if (error) { TRACE_ERROR_NUMBER("Failed to create meta data", error); return error; } /* Check and create section for file error if needed */ if (metaflags & INI_META_SEC_ERROR_FLAG) { /* Create ERROR collection */ if ((error = col_create_collection(&metasec, INI_META_SEC_ERROR, COL_CLASS_INI_SECTION)) || (error = col_add_collection_to_collection( *metadata, NULL, NULL, metasec, COL_ADD_MODE_REFERENCE))) { TRACE_ERROR_NUMBER("Failed to create error section", error); col_destroy_collection(metasec); col_destroy_collection(*metadata); *metadata = NULL; return error; } /* If we are here we would have to save file open error */ *save_error = 1; col_destroy_collection(metasec); } TRACE_FLOW_STRING("prepare_metadata", "Exit"); return error; }
/* Function to add string to the end of the buffer. */ int simplebuffer_add_str(struct simplebuffer *data, const char *str, uint32_t len, uint32_t block) { int error = EOK; uint32_t size; TRACE_FLOW_ENTRY(); size = len + 1; error = simplebuffer_grow(data, size, ((block > size) ? block : size)); if (error) { TRACE_ERROR_NUMBER("Failed to grow buffer.", error); return error; } memcpy(data->buffer + data->length, str, len); data->length += len; data->buffer[data->length] = '\0'; TRACE_FLOW_EXIT(); return error; }
/* Grow buffer to accomodate more space */ int col_grow_buffer(struct col_serial_data *buf_data, int len) { char *tmp; TRACE_FLOW_STRING("col_grow_buffer", "Entry point"); TRACE_INFO_NUMBER("Current length: ", buf_data->length); TRACE_INFO_NUMBER("Increment length: ", len); TRACE_INFO_NUMBER("Expected length: ", buf_data->length+len); TRACE_INFO_NUMBER("Current size: ", buf_data->size); /* Grow buffer if needed */ while (buf_data->length+len >= buf_data->size) { tmp = realloc(buf_data->buffer, buf_data->size + BLOCK_SIZE); if (tmp == NULL) { TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM); return ENOMEM; } buf_data->buffer = tmp; buf_data->size += BLOCK_SIZE; TRACE_INFO_NUMBER("New size: ", buf_data->size); } TRACE_INFO_NUMBER("Final size: ", buf_data->size); TRACE_FLOW_STRING("col_grow_buffer", "Success Exit."); return EOK; }
static int ref_array_grow(struct ref_array *ra) { int error = EOK; void *newbuf = NULL; TRACE_FLOW_ENTRY(); TRACE_INFO_NUMBER("Current length: ", ra->len); TRACE_INFO_NUMBER("Current size: ", ra->size); /* Grow buffer if needed */ newbuf = realloc(ra->storage, (ra->size + ra->grow_by) * ra->elsize); if (newbuf == NULL) { TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); return ENOMEM; } ra->storage = newbuf; ra->size += ra->grow_by; TRACE_INFO_NUMBER("Final size: ", ra->size); TRACE_FLOW_RETURN(error); return error; }
/* Create a buffer containg JSON serialization */ int col_json_collection(struct collection_item *handle, char **storage) { struct col_serial_data buf_data; int error = EOK; TRACE_FLOW_STRING("col_json_collection", "Entry"); if (storage == NULL) { TRACE_ERROR_STRING("Error.", "Storage data is not passed in!"); return EINVAL; } *storage = NULL; buf_data.buffer = NULL; buf_data.length = 0; buf_data.size = 0; buf_data.nest_level = 0; /* Traverse collection */ error = col_traverse_collection(handle, COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END , col_json, (void *)(&buf_data)); if (error) TRACE_ERROR_NUMBER("Error traversing collection ", error); else *storage = buf_data.buffer; TRACE_FLOW_NUMBER("col_json_collection returning", error); return error; }
/* Grow buffer */ int simplebuffer_grow(struct simplebuffer *data, uint32_t len, uint32_t block) { int error = EOK; unsigned char *newbuf = NULL; TRACE_FLOW_ENTRY(); TRACE_INFO_NUMBER("Current length: ", data->length); TRACE_INFO_NUMBER("Current size: ", data->size); TRACE_INFO_NUMBER("Length to have: ", len); TRACE_INFO_NUMBER("Increment length: ", block); /* Grow buffer if needed */ while (data->length + len >= data->size) { newbuf = realloc(data->buffer, data->size + block); if (newbuf == NULL) { TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM); return ENOMEM; } data->buffer = newbuf; data->size += block; TRACE_INFO_NUMBER("New size: ", data->size); } TRACE_INFO_NUMBER("Final size: ", data->size); TRACE_FLOW_RETURN(error); return error; }
/* Insert a new element into the array */ int ref_array_insert(struct ref_array *ra, uint32_t idx, void *element) { int error = EOK; uint32_t i; TRACE_FLOW_ENTRY(); if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if (idx > ra->len) { TRACE_ERROR_NUMBER("Index is out of range", ERANGE); return ERANGE; } /* Do we have enough room for a new element? */ if (ra->size == ra->len) { error = ref_array_grow(ra); if (error) { TRACE_ERROR_NUMBER("Failed to grow array.", error); return error; } } /* Shift elements right */ for (i = ra->len; i >= (idx + 1); i--) { memcpy((unsigned char *)(ra->storage) + i * ra->elsize, (unsigned char *)(ra->storage) + (i - 1) * ra->elsize, ra->elsize); } /* Overwrite element */ memcpy((unsigned char *)(ra->storage) + idx * ra->elsize, element, ra->elsize); ra->len++; TRACE_FLOW_EXIT(); return error; }
/* Function to check whether the configuration is different */ int config_changed(struct collection_item *metadata, struct collection_item *saved_metadata, int *changed) { int error = EOK; struct collection_item *md[2]; unsigned long value[3][2]; const char *key[] = { INI_META_KEY_MODIFIED, INI_META_KEY_DEV, INI_META_KEY_INODE }; int i, j; TRACE_FLOW_STRING("config_changed", "Entry"); if ((!metadata) || (!saved_metadata) || (!changed) || (!col_is_of_class(metadata, COL_CLASS_INI_META)) || (!col_is_of_class(saved_metadata, COL_CLASS_INI_META))) { TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); return EINVAL; } md[0] = metadata; md[1] = saved_metadata; /* Get three values from each collection and compare them */ for (i = 0; i < 3; i++) { for (j = 0; j < 2; j++) { value[i][j] = get_checked_value(md[j], key[i] , &error); if (error) { TRACE_ERROR_NUMBER("Failed to get section.", error); return error; } } if (value[i][0] != value[i][1]) { *changed = 1; break; } } TRACE_FLOW_STRING("config_changed", "Exit"); return error; }
/* Swap two elements in the array */ int ref_array_swap(struct ref_array *ra, uint32_t idx1, uint32_t idx2) { int error = EOK; void *temp = NULL; TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if ((idx1 >= ra->len) || (idx2 >= ra->len)) { TRACE_ERROR_NUMBER("Index is out of range", ERANGE); return ERANGE; } if (idx1 == idx2) { TRACE_FLOW_STRING("ref_array_swap", "Noop return"); return EOK; } temp = malloc(ra->elsize); if (!temp) { TRACE_FLOW_STRING("Failed to allocate memory for temp storage.", ""); return ENOMEM; } memcpy(temp, (unsigned char *)(ra->storage) + idx2 * ra->elsize, ra->elsize); memcpy((unsigned char *)(ra->storage) + idx2 * ra->elsize, (unsigned char *)(ra->storage) + idx1 * ra->elsize, ra->elsize); memcpy((unsigned char *)(ra->storage) + idx1 * ra->elsize, temp, ra->elsize); free(temp); TRACE_FLOW_EXIT(); return error; }
/* Process comment */ static int handle_comment(struct parser_obj *po, uint32_t *action) { int error = EOK; TRACE_FLOW_ENTRY(); /* We got a comment */ if (po->key) { /* Previous value if any is complete */ error = complete_value_processing(po); if (error) { TRACE_ERROR_NUMBER("Failed to finish saving value", error); return error; } } if (!(po->ic)) { /* Create a new comment */ error = ini_comment_create(&(po->ic)); if (error) { TRACE_ERROR_NUMBER("Failed to create comment", error); return error; } } /* Add line to comment */ error = ini_comment_build_wl(po->ic, po->last_read, po->last_read_len); if (error) { TRACE_ERROR_NUMBER("Failed to add line to comment", error); return error; } /* * We are done with the comment line. * Free it since comment keeps a copy. */ free(po->last_read); po->last_read = NULL; po->last_read_len = 0; *action = PARSE_READ; TRACE_FLOW_EXIT(); return EOK; }
static unsigned long get_checked_value(struct collection_item *metadata, const char *key, int *err) { int error = EOK; struct collection_item *item = NULL; unsigned long value; TRACE_FLOW_STRING("get_checked_value", "Entry"); TRACE_INFO_STRING("Key", key); error = get_config_item(INI_META_SEC_ACCESS, key, metadata, &item); if (error) { TRACE_ERROR_NUMBER("Internal collection error.", error); *err = error; return 0; } /* Entry is supposed to be there so it is an error * is the item is not found. */ if (item == NULL) { TRACE_ERROR_NUMBER("Expected item is not found.", ENOENT); *err = ENOENT; return 0; } value = get_ulong_config_value(item, 1, -1, &error); if ((error) || (value == -1)) { TRACE_ERROR_NUMBER("Conversion failed", EINVAL); *err = EINVAL; return 0; } *err = 0; TRACE_FLOW_NUMBER("get_checked_value Returning", value); return value; }
/* Copy configuration */ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new) { int error = EOK; struct ini_cfgobj *new_co; TRACE_FLOW_ENTRY(); if ((!ini_config) || (!ini_new)) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } /* Create a new configuration object */ errno = 0; new_co = malloc(sizeof(struct ini_cfgobj)); if (!new_co) { error = errno; TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM); return ENOMEM; } new_co->cfg = NULL; new_co->boundary = ini_config->boundary; error = col_copy_collection_with_cb(&(new_co->cfg), ini_config->cfg, INI_CONFIG_NAME, COL_COPY_NORMAL, ini_copy_cb, NULL); if (error) { TRACE_ERROR_NUMBER("Failed to copy collection", error); ini_config_destroy(new_co); return error; } *ini_new = new_co; TRACE_FLOW_EXIT(); return error; }
/* Create referenced array */ int ref_array_create(struct ref_array **ra, size_t elemsz, uint32_t grow_by, ref_array_fn cb, void *data) { struct ref_array *new_ra = NULL; TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; } if ((!elemsz) || (!grow_by)) { TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); return EINVAL; } new_ra = (struct ref_array *)malloc(sizeof(struct ref_array)); if (!new_ra) { TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); return ENOMEM; } new_ra->storage = NULL; new_ra->elsize = elemsz; new_ra->size = 0; new_ra->grow_by = grow_by; new_ra->len = 0; new_ra->refcount = 1; new_ra->cb = cb; new_ra->cb_data = data; *ra = new_ra; TRACE_FLOW_EXIT(); return EOK; }
/* Create a pair of arrays */ int value_create_arrays(struct ref_array **raw_lines, struct ref_array **raw_lengths) { int error = EOK; struct ref_array *new_lines = NULL; struct ref_array *new_lengths = NULL; TRACE_FLOW_ENTRY(); error = ref_array_create(&new_lines, sizeof(char *), INI_ARRAY_GROW, value_lines_cleanup_cb, NULL); if (error) { TRACE_ERROR_NUMBER("Failed to create lines array", error); return error; } error = ref_array_create(&new_lengths, sizeof(uint32_t), INI_ARRAY_GROW, NULL, NULL); if (error) { TRACE_ERROR_NUMBER("Failed to create lengths array", error); ref_array_destroy(new_lines); return error; } *raw_lines = new_lines; *raw_lengths = new_lengths; TRACE_FLOW_EXIT(); return EOK; }
/* Create a config object */ int ini_config_create(struct ini_cfgobj **ini_config) { int error = EOK; struct ini_cfgobj *new_co = NULL; TRACE_FLOW_ENTRY(); if (!ini_config) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } errno = 0; new_co = malloc(sizeof(struct ini_cfgobj)); if (!new_co) { error = errno; TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM); return ENOMEM; } new_co->cfg = NULL; new_co->boundary = INI_WRAP_BOUNDARY; /* Create a collection to hold configuration data */ error = col_create_collection(&(new_co->cfg), INI_CONFIG_NAME, COL_CLASS_INI_CONFIG); if (error != EOK) { TRACE_ERROR_NUMBER("Failed to create collection.", error); ini_config_destroy(new_co); return error; } *ini_config = new_co; TRACE_FLOW_EXIT(); return error; }
/* Get value's line */ int value_get_line(struct value_obj *vo, uint32_t *line) { TRACE_FLOW_ENTRY(); if (!vo) { TRACE_ERROR_NUMBER("Invalid object", EINVAL); return EINVAL; } *line = vo->line; TRACE_FLOW_EXIT(); return EOK; }