Esempio n. 1
0
/* Get element */
void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr)
{
    TRACE_FLOW_ENTRY();

    if (!ra) {
        TRACE_ERROR_STRING("Uninitialized argument.", "");
        return NULL;
    }

    if (idx >= ra->len) {
        TRACE_INFO_NUMBER("Invalid idx.", idx);
        return NULL;
    }

    TRACE_INFO_NUMBER("Index: ", idx);

    if (acptr) {

        TRACE_INFO_STRING("Copying data.", "");
        memcpy(acptr,
               (unsigned char *)(ra->storage) + idx * ra->elsize,
               ra->elsize);

    }

    TRACE_FLOW_EXIT();
    return (unsigned char *)(ra->storage) + idx * ra->elsize;
}
Esempio n. 2
0
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 *)(&copy));
    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;
}
Esempio n. 3
0
/* 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;
}
Esempio n. 4
0
/* 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;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
0
/* 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;
}
Esempio n. 7
0
/* Find if there is a collistion */
static int check_section_collision(struct parser_obj *po)
{
    int error = EOK;
    struct collection_item *item = NULL;

    TRACE_FLOW_ENTRY();

    TRACE_INFO_STRING("Searching for:", col_get_item_property(po->sec, NULL));

    error = col_get_item(po->top,
                         col_get_item_property(po->sec, NULL),
                         COL_TYPE_ANY,
                         COL_TRAVERSE_DEFAULT,
                         &item);

    if (error) {
        TRACE_ERROR_NUMBER("Failed searching for dup", error);
        return error;
    }

    /* Check if there is a dup */
    if (item) {
        TRACE_INFO_STRING("Collision found:",
                          col_get_item_property(item, NULL));
        /* Get the actual section collection instead of reference */
        po->merge_sec = *((struct collection_item **)
                          (col_get_item_data(item)));
    }
    else {
        TRACE_INFO_STRING("Collision not found.", "");
        po->merge_sec = NULL;
    }

    TRACE_FLOW_EXIT();
    return EOK;
}
Esempio n. 8
0
/* Cleanup callback for lines array */
void value_lines_cleanup_cb(void *elem,
                            ref_array_del_enum type,
                            void *data)
{
    char *part;

    TRACE_FLOW_ENTRY();

    part = *((char **)(elem));

    TRACE_INFO_STRING("Freeing:", part);

    free(part);

    TRACE_FLOW_EXIT();
}
Esempio n. 9
0
/* Function to check uid or gid */
static int check_id(struct collection_item *metadata,
                    unsigned long id,
                    const char *key)
{
    int error = EOK;
    struct collection_item *item = NULL;
    unsigned long fid;

    TRACE_FLOW_STRING("check_id", "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);
        return error;
    }

    /* 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);
        return ENOENT;
    }

    fid = get_ulong_config_value(item, 1, -1, &error);
    if ((error) || (fid == -1)) {
        TRACE_ERROR_NUMBER("Conversion failed", EINVAL);
        return EINVAL;
    }

    if (id != fid) {
        TRACE_ERROR_NUMBER("File ID:", fid);
        TRACE_ERROR_NUMBER("ID passed in.", id);
        TRACE_ERROR_NUMBER("Access denied.", EACCES);
        return EACCES;
    }

    TRACE_FLOW_STRING("check_id", "Exit");
    return EOK;
}
Esempio n. 10
0
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;

}
Esempio n. 11
0
/* Delete the array */
void ref_array_destroy(struct ref_array *ra)
{
    int idx;

    TRACE_FLOW_ENTRY();

    /* Check if array is not NULL */
    if (!ra) {
        TRACE_INFO_STRING("Uninitialized array.", "Might be Ok...");
        return;
    }

    TRACE_INFO_NUMBER("Current reference count: ", ra->refcount);
    if (ra->refcount) {
        /* Decrease reference count */
        ra->refcount--;
        if (ra->refcount == 0) {
            TRACE_INFO_NUMBER("It is time to delete array. Count:", ra->refcount);
            if (ra->cb) {
                for (idx = 0; idx < ra->len; idx++) {
                    ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize,
                            REF_ARRAY_DESTROY, ra->cb_data);
                }
            }
            free(ra->storage);
            free(ra);
        }
    }
    else {
        /* Should never be here...
         * This can happen if the caller by mistake would try to
         * destroy the object from within the callback. Brrr....
         */
        TRACE_ERROR_STRING("Reference count is 0.", "Coding error???");
    }

    TRACE_FLOW_EXIT();
}
Esempio n. 12
0
/* Get items from the collection one by one following the tree */
int col_iterate_collection(struct collection_iterator *iterator,
                           struct collection_item **item)
{
    int error;
    struct collection_item *current;
    struct collection_item *other;

    TRACE_FLOW_STRING("col_iterate_collection", "Entry.");

    /* Check if we have storage for item */
    if (item == NULL) {
        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
        return EINVAL;
    }

    while (1) {

        TRACE_INFO_NUMBER("Stack depth:", iterator->stack_depth);

        if (iterator->stack_depth == 0) {
            /* Re-init so if we continue looping we start over */
            iterator->stack[0] = iterator->top;
            iterator->stack_depth++;
            iterator->item_level = 0;
        }

        /* Is current item available */
        current = iterator->stack[iterator->stack_depth - 1];
        iterator->item_level = iterator->stack_depth - 1;

        /* Are we done? */
        if (((iterator->stack_depth - 1) == iterator->pin_level) &&
            (iterator->pin == current)) {
            if (iterator->can_break) {
                TRACE_FLOW_STRING("We are done.", "");
                *item = NULL;
                iterator->can_break = 0;
                return EOK;
            }
            else iterator->can_break = 1;
        }

        /* We are not done so check if we have an item  */
        if (current != NULL) {

            TRACE_INFO_STRING("Current item:", current->property);
            TRACE_INFO_NUMBER("Current item type:", current->type);

            /* Is this a collection reference */
            if (current->type == COL_TYPE_COLLECTIONREF) {
                /* We do follow references? */
                TRACE_INFO_STRING("Current item:", "collection reference");
                if ((iterator->flags & COL_TRAVERSE_IGNORE) == 0) {
                    /* We should not ignore - then move on */
                    TRACE_INFO_STRING("Collection references are not ignored", "");
                    error = col_grow_stack(iterator, iterator->stack_depth + 1);
                    if (error) {
                        TRACE_ERROR_NUMBER("Error growing stack.", error);
                        return error;
                    }
                    /* Do we need to go deeper than one level ? */
                    if ((iterator->flags & COL_TRAVERSE_ONELEVEL) == 0) {
                        TRACE_INFO_STRING("Need to go deeper", "");
                        /* We need to go deeper... */
                        /* Do we need to show headers but not reference? */
                        if ((iterator->flags & COL_TRAVERSE_ONLYSUB) != 0) {
                            TRACE_INFO_STRING("Instructed to show header not reference", "");
                            other = *((struct collection_item **)current->data);
                            iterator->stack[iterator->stack_depth] = other->next;
                            iterator->item_level = iterator->stack_depth;
                            *item = other;
                        }
                        /* Do we need to show both? */
                        else if ((iterator->flags & COL_TRAVERSE_SHOWSUB) != 0) {
                            TRACE_INFO_STRING("Instructed to show header and reference","");
                            iterator->stack[iterator->stack_depth] = *((struct collection_item **)(current->data));
                            *item = current;
                            /* Do not need to adjust level here */
                        }
                        /* Do not show either */
                        else if ((iterator->flags & COL_TRAVERSE_FLAT) != 0) {
                            TRACE_INFO_STRING("Instructed not to show header and reference","");
                            other = *((struct collection_item **)current->data);
                            iterator->stack[iterator->stack_depth] = other->next;
                            iterator->stack[iterator->stack_depth - 1] = current->next;
                            iterator->stack_depth++;
                            /* Do not need to adjust level here */
                            continue;
                        }
                        /* We need to show reference only */
                        else {
                            TRACE_INFO_STRING("Instructed to show reference only", "");
                            other = *((struct collection_item **)current->data);
                            TRACE_INFO_STRING("Sub collection:", other->property);
                            TRACE_INFO_NUMBER("Sub collection type:", other->type);
                            iterator->stack[iterator->stack_depth] = other->next;
                            if (other->next != NULL) {
                                TRACE_INFO_STRING("Will show this item next time:", other->next->property);
                                TRACE_INFO_NUMBER("Will show this item next time type:", other->next->type);
                            }
                            *item = current;
                            TRACE_INFO_NUMBER("Level of the reference:", iterator->item_level);
                            /* Do not need to adjust level here */
                        }

                        TRACE_INFO_STRING("We return item:", (*item)->property);
                        TRACE_INFO_NUMBER("We return item type:", (*item)->type);
                        TRACE_INFO_STRING("Moving to the next item on the previous item in stack", "");
                        iterator->stack[iterator->stack_depth - 1] = current->next;
                        iterator->stack_depth++;

                    }
                    else {
                        TRACE_INFO_STRING("Instructed to parse just one level", "");
                        /* On one level - just return current */
                        *item = current;
                        TRACE_INFO_STRING("Moving to the next item on one level", "");
                        iterator->stack[iterator->stack_depth - 1] = current->next;
                    }
                    break;
                }
                else {
                    /* We need to ignore references so move to the next item */
                    TRACE_INFO_STRING("Stepping over the reference", "");
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                    continue;
                }
            }
            else {
                /* Got a normal item - return it and move to the next one */
                if ((current->type == COL_TYPE_COLLECTION) &&
                    ((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
                    (iterator->stack_depth > 1)) {
                    TRACE_INFO_STRING("Header of the sub collection in flat case ", "");
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                    continue;
                }
                else {
                    TRACE_INFO_STRING("Simple item", "");
                    *item = current;
                    iterator->stack[iterator->stack_depth - 1] = current->next;
                }
                break;
            }
        }
        else {
            /* Item is NULL */
            TRACE_INFO_STRING("Finished level", "moving to upper level");
            iterator->stack_depth--;
            /* Remember that item_level is zero based while depth is size
             * so we decrease and then assign. */
            TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
            if ((iterator->flags & COL_TRAVERSE_END) != 0) {

                /* Show end element
                 * a) If we are flattening but at the top
                 * b) We are not flattening
                 */
                if ((((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
                     (iterator->stack_depth == 0)) ||
                    ((iterator->flags & COL_TRAVERSE_FLAT) == 0)) {

                    /* Return dummy entry to indicate the end of the collection */
                    TRACE_INFO_STRING("Finished level", "told to return END");
                    *item = iterator->end_item;
                    break;
                }
            }
            else {
                /* Move to next level */
                continue;
            }
        }
    }

    TRACE_FLOW_STRING("col_iterate_collection", "Exit");
    return EOK;
}
Esempio n. 13
0
/* Use JSON formal for serialization */
int col_json(const char *property_in,
             int property_len_in,
             int type,
             void *data_in,
             int length_in,
             void *custom_data,
             int *dummy)
{
    int len;
    struct col_serial_data *buf_data;
    const char *property;
    const void *data;
    int  property_len;
    int length;
    int error = EOK;
    int i;

    TRACE_FLOW_STRING("col_json","Entry point");

    *dummy = 0;

    /* Check is there is buffer. If not allocate */
    buf_data = (struct col_serial_data *)custom_data;
    if (buf_data == NULL) {
        TRACE_ERROR_STRING("Error.", "Storage data is not passed in!");
        return EINVAL;
    }
    if (buf_data->buffer == NULL) {
        TRACE_INFO_STRING("First time use.", "Allocating buffer.");
        buf_data->buffer = malloc(BLOCK_SIZE);
        if (buf_data->buffer == NULL) {
            TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
            return ENOMEM;
        }
        buf_data->buffer[0] = '\0';
        buf_data->length = 0;
        buf_data->size = BLOCK_SIZE;
    }

    TRACE_INFO_NUMBER("Buffer len: ", buf_data->length);
    TRACE_INFO_NUMBER("Buffer size: ", buf_data->size);
    TRACE_INFO_STRING("Buffer: ", buf_data->buffer);

    /* Check the beginning of the collection */
    if (type == COL_TYPE_COLLECTION) {
        TRACE_INFO_STRING("Serializing collection: ", property_in);
        TRACE_INFO_STRING("First header. ", "");
        error = col_put_marker(buf_data, "{", 1);
        if (error != EOK) return error;
        property = TEXT_EVENT;
        property_len = TEXT_EVENTLEN;
        data = property_in;
        length = property_len_in + 1;
        type = COL_TYPE_STRING;
        buf_data->nest_level++;
    }
    /* Check for subcollections */
    else if (type == COL_TYPE_COLLECTIONREF) {
        /* Skip */
        TRACE_FLOW_STRING("col_serialize", "skip reference return");
        return EOK;
    }
    /* Check for the end of the collection */
    else if (type == COL_TYPE_END) {
        if ((buf_data->length > 0) &&
                (buf_data->buffer[buf_data->length-1] == ',')) {
            buf_data->length--;
            buf_data->buffer[buf_data->length] = '\0';
        }
        if (buf_data->nest_level > 0) {
            buf_data->nest_level--;
            error = col_put_marker(buf_data, "}", 1);
            if (error != EOK) return error;
        }
        TRACE_FLOW_STRING("col_serialize", "end collection item processed returning");
        return EOK;
    }
    else {
        property = property_in;
        property_len = property_len_in;
        data = data_in;
        length = length_in;
    }

    TRACE_INFO_STRING("Property: ", property);
    TRACE_INFO_NUMBER("Property length: ", property_len);

    /* Start with property and ":" */
    if ((error = col_put_marker(buf_data, "\"", 1)) ||
            (error = col_put_marker(buf_data, property, property_len)) ||
            (error = col_put_marker(buf_data, "\":", 2))) {
        TRACE_ERROR_NUMBER("put_marker returned error: ", error);
        return error;
    }
    /* Get projected length of the item */
    len = col_get_data_len(type,length);
    TRACE_INFO_NUMBER("Expected data length: ",len);
    TRACE_INFO_STRING("Buffer so far: ", buf_data->buffer);

    /* Make sure we have enough space */
    if ((error = col_grow_buffer(buf_data, len))) {
        TRACE_ERROR_NUMBER("grow_buffer returned error: ", error);
        return error;
    }

    /* Add the value */
    switch (type) {
    case COL_TYPE_STRING:
        /* Escape double quotes */
        len = col_copy_esc(&buf_data->buffer[buf_data->length],
                           (const char *)(data), '"');
        break;

    case COL_TYPE_BINARY:
        buf_data->buffer[buf_data->length] = '\'';
        for (i = 0; i < length; i++)
            sprintf(&buf_data->buffer[buf_data->length + i *2] + 1,
                    "%02X", (unsigned int)(((const unsigned char *)(data))[i]));
        len = length * 2 + 1;
        buf_data->buffer[buf_data->length + len] = '\'';
        len++;
        break;

    case COL_TYPE_INTEGER:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%d", *((const int32_t *)(data)));
        break;

    case COL_TYPE_UNSIGNED:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%u", *((const uint32_t *)(data)));
        break;

    case COL_TYPE_LONG:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%lld",
                      (long long int)(*((const int64_t *)(data))));
        break;

    case COL_TYPE_ULONG:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%llu",
                      (long long unsigned)(*((const uint64_t *)(data))));
        break;

    case COL_TYPE_DOUBLE:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%.4f", *((const double *)(data)));
        break;

    case COL_TYPE_BOOL:
        len = sprintf(&buf_data->buffer[buf_data->length],
                      "%s", (*((const unsigned char *)(data))) ? "true" : "false");
        break;

    default:
        buf_data->buffer[buf_data->length] = '\0';
        len = 0;
        break;
    }

    /* Adjust length */
    buf_data->length += len;
    buf_data->buffer[buf_data->length] = '\0';

    /* Always put a comma at the end */
    error = col_put_marker(buf_data, ",", 1);
    if (error != EOK) {
        TRACE_ERROR_NUMBER("put_marker returned error: ", error);
        return error;
    }

    TRACE_INFO_STRING("Data: ", buf_data->buffer);
    TRACE_FLOW_STRING("col_json", "Exit point");
    return EOK;

}
Esempio n. 14
0
/* Handle key-value pair */
static int handle_kvp(struct parser_obj *po, uint32_t *action)
{
    int error = EOK;
    char *eq = NULL;
    uint32_t len = 0;
    char *dupval = NULL;
    char *str;
    uint32_t full_len;

    TRACE_FLOW_ENTRY();

    str = po->last_read;
    full_len = po->last_read_len;

    TRACE_INFO_STRING("Last read:", str);

    /* Trim spaces at the beginning */
    while ((full_len > 0) && (isspace(*(str)))) {
        str++;
        full_len--;
    }

    /* Check if we have the key */
    if (*(str) == '=') {
        TRACE_ERROR_STRING("No key", str);
        po->last_error = ERR_NOKEY;
        *action = PARSE_ERROR;
        return EOK;
    }

    /* Find "=" */
    eq = strchr(str, '=');
    if (eq == NULL) {
        TRACE_ERROR_STRING("No equal sign", str);
        po->last_error = ERR_NOEQUAL;
        *action = PARSE_ERROR;
        return EOK;
    }

    /* Strip spaces around "=" */
    /* Since eq > str we can substract 1 */
    len = eq - str - 1;
    while ((len > 0) && (isspace(*(str + len)))) len--;
    /* Adjust length properly */
    len++;

    /* Check the key length */
    if(len >= MAX_KEY) {
        TRACE_ERROR_STRING("Key name is too long", str);
        po->last_error = ERR_LONGKEY;
        *action = PARSE_ERROR;
        return EOK;
    }

    if (po->key) {
        /* Complete processing of the previous value */
        error = complete_value_processing(po);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to complete value processing", error);
            return error;
        }
    }

    /* Dup the key name */
    po->key = malloc(len + 1);
    if (!(po->key)) {
        TRACE_ERROR_NUMBER("Failed to dup key", ENOMEM);
        return ENOMEM;
    }

    memcpy(po->key, str, len);
    *(po->key + len) = '\0';
    po->key_len = len;

    TRACE_INFO_STRING("Key:", po->key);
    TRACE_INFO_NUMBER("Keylen:", po->key_len);

    len = full_len - (eq - str) - 1;

    /* Trim spaces after equal sign */
    eq++;
    while (isspace(*eq)) {
        eq++;
        len--;
    }

    TRACE_INFO_STRING("VALUE:", eq);
    TRACE_INFO_NUMBER("LENGTH:", len);

    /* Dup the part of the value */
    dupval = malloc(len + 1);
    if (!dupval) {
        TRACE_ERROR_NUMBER("Failed to dup value", ENOMEM);
        return ENOMEM;
    }

    memcpy(dupval, eq, len);
    *(dupval + len) = '\0';

    /* Create new arrays */
    error = value_create_arrays(&(po->raw_lines),
                                &(po->raw_lengths));
    if (error) {
        TRACE_ERROR_NUMBER("Failed to create arrays", error);
        free(dupval);
        return error;
    }

    /* Save a duplicated part in the value */
    error = value_add_to_arrays(dupval,
                                len,
                                po->raw_lines,
                                po->raw_lengths);

    if (error) {
        TRACE_ERROR_NUMBER("Failed to add value to arrays", error);
        free(dupval);
        return error;
    }

    /* Save the line number of the last found key */
    po->keylinenum = po->linenum;

    /* Prepare for reading */
    free(po->last_read);
    po->last_read = NULL;
    po->last_read_len = 0;

    *action = PARSE_READ;

    TRACE_FLOW_EXIT();
    return EOK;
}
Esempio n. 15
0
/* Complete value processing */
static int complete_value_processing(struct parser_obj *po)
{
    int error = EOK;
    int error2 = EOK;
    struct value_obj *vo = NULL;
    struct value_obj *vo_old = NULL;
    unsigned insertmode;
    uint32_t mergemode;
    int suppress = 0;
    int doinsert = 0;
    struct collection_item *item = NULL;
    struct collection_item *section = NULL;
    int merging = 0;

    TRACE_FLOW_ENTRY();

    if (po->merge_sec) {
        TRACE_INFO_STRING("Processing value in merge mode", "");
        section = po->merge_sec;
        merging = 1;
    }
    else if(!(po->sec)) {
        TRACE_INFO_STRING("Creating default section", "");
        /* If there is not open section create a default one */
        error = col_create_collection(&po->sec,
                                      INI_DEFAULT_SECTION,
                                      COL_CLASS_INI_SECTION);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to create default section", error);
            return error;
        }
        section = po->sec;
    }
    else {
        TRACE_INFO_STRING("Processing value in normal mode", "");
        section = po->sec;
    }

    if (merging) {
        TRACE_INFO_STRING("Using merge key:", po->merge_key);
        vo = po->merge_vo;
        /* We are adding to the merge section so use MV2S flags.
         * But flags are done in such a way that deviding MV2S by MV1S mask
         * will translate MV2S flags into MV1S so we can use
         * MV1S constants. */
        TRACE_INFO_NUMBER("Collisions flags:", po->collision_flags);
        mergemode = (po->collision_flags & INI_MV2S_MASK) / INI_MV1S_MASK;
    }
    else {
        /* Construct value object from what we have */
        error = value_create_from_refarray(po->raw_lines,
                                           po->raw_lengths,
                                           po->keylinenum,
                                           INI_VALUE_READ,
                                           po->key_len,
                                           po->boundary,
                                           po->ic,
                                           &vo);

        if (error) {
            TRACE_ERROR_NUMBER("Failed to create value object", error);
            return error;
        }
        /* Forget about the arrays. They are now owned by the value object */
        po->ic = NULL;
        po->raw_lines = NULL;
        po->raw_lengths = NULL;
        mergemode = po->collision_flags & INI_MV1S_MASK;
    }

    switch (mergemode) {
    case INI_MV1S_ERROR:

        insertmode = COL_INSERT_DUPERROR;
        doinsert = 1;
        break;

    case INI_MV1S_PRESERVE:

        insertmode = COL_INSERT_DUPERROR;
        doinsert = 1;
        suppress = 1;
        break;

    case INI_MV1S_ALLOW:

        insertmode = COL_INSERT_NOCHECK;
        doinsert = 1;
        break;

    case INI_MV1S_OVERWRITE: /* Special handling */
    case INI_MV1S_DETECT:
    default:
        break;
    }

    /* Do not insert but search for dups first */
    if (!doinsert) {
        TRACE_INFO_STRING("Overwrite mode. Looking for:",
                          (char *)(merging ? po->merge_key : po->key));

        error = col_get_item(section,
                             merging ? po->merge_key : po->key,
                             COL_TYPE_BINARY,
                             COL_TRAVERSE_DEFAULT,
                             &item);

        if (error) {
            TRACE_ERROR_NUMBER("Failed searching for dup", error);
            value_destroy(vo);
            return error;
        }

        /* Check if there is a dup */
        if (item) {
            /* Check if we are in the detect mode */
            if (mergemode == INI_MV1S_DETECT) {
                po->merge_error = EEXIST;
                /* There is a dup - inform user about it and continue */
                error = save_error(po->el,
                                   merging ? po->seclinenum : po->keylinenum,
                                   merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
                                   ERROR_TXT);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to save error", error);
                    value_destroy(vo);
                    return error;
                }
                doinsert = 1;
                insertmode = COL_INSERT_NOCHECK;

            }
            else {

                /* Dup exists - update it */
                vo_old = *((struct value_obj **)(col_get_item_data(item)));
                error = col_modify_binary_item(item,
                                               NULL,
                                               &vo,
                                               sizeof(struct value_obj *));
                if (error) {
                    TRACE_ERROR_NUMBER("Failed updating the value", error);
                    value_destroy(vo);
                    return error;
                }

                /* If we failed to update it is better to leak then crash,
                 * so destroy original value only on the successful update.
                 */
                value_destroy(vo_old);
            }
        }
        else {
            /* No dup found so we can insert with no check */
            doinsert = 1;
            insertmode = COL_INSERT_NOCHECK;
        }
    }

    if (doinsert) {
        /* Add value to collection */
        error = col_insert_binary_property(section,
                                           NULL,
                                           COL_DSP_END,
                                           NULL,
                                           0,
                                           insertmode,
                                           merging ? po->merge_key : po->key,
                                           &vo,
                                           sizeof(struct value_obj *));
        if (error) {
            value_destroy(vo);

            if ((suppress) && (error == EEXIST)) {
                TRACE_INFO_STRING("Preseved exisitng value",
                                  (char *)(merging ? po->merge_key : po->key));
            }
            else {
                /* Check if this is a critical error or not */
                if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
                    TRACE_ERROR_NUMBER("Failed to add value object "
                                       "to the section", error);
                    error2 = save_error(po->el,
                                       merging ? po->seclinenum : po->keylinenum,
                                       merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
                                       ERROR_TXT);
                    if (error2) {
                        TRACE_ERROR_NUMBER("Failed to save error", error2);
                        return error2;
                    }
                    return error;
                }
                else {
                    TRACE_ERROR_NUMBER("Failed to add value object"
                                       " to the section", error);
                    return error;
                }
            }
        }
    }

    if (!merging) {
        free(po->key);
        po->key = NULL;
        po->key_len = 0;
    }

    TRACE_FLOW_EXIT();
    return EOK;
}
Esempio n. 16
0
/* Function to read next line from the file */
static int parser_save_section(struct parser_obj *po)
{
    int error = EOK;
    uint32_t mergemode;
    int merge = 0;

    TRACE_FLOW_ENTRY();

    if (po->sec) {

        TRACE_INFO_STRING("Section exists.", "");

        /* First detect if we have collision */
        error = check_section_collision(po);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to check for collision", error);
            return error;
        }

        if (po->merge_sec) {

            TRACE_INFO_STRING("Merge collision detected", "");

            mergemode = po->collision_flags & INI_MS_MASK;

            switch (mergemode) {
            case INI_MS_ERROR:
                /* Report error and return */
                TRACE_INFO_STRING("Reporting error", "duplicate section");
                error = save_error(po->el,
                                   po->seclinenum,
                                   ERR_DUPSECTION,
                                   ERROR_TXT);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "save error",
                                        error);
                    return error;
                }
                /* Return error */
                TRACE_FLOW_RETURN(EEXIST);
                return EEXIST;

            case INI_MS_PRESERVE:
                /* Delete new section */
                TRACE_INFO_STRING("Preserve mode", "");
                col_destroy_collection_with_cb(
                                        po->sec,
                                        ini_cleanup_cb,
                                        NULL);
                po->sec = NULL;
                break;

            case INI_MS_OVERWRITE:
                /* Empty existing section */
                TRACE_INFO_STRING("Ovewrite mode", "");
                error = empty_section(po->merge_sec);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "empty section",
                                        error);
                    return error;
                }
                merge = 1;
                break;

            case INI_MS_DETECT:
                /* Detect mode */
                TRACE_INFO_STRING("Detect mode", "");
                po->merge_error = EEXIST;
                error = save_error(po->el,
                                   po->seclinenum,
                                   ERR_DUPSECTION,
                                   ERROR_TXT);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to "
                                       "save error",
                                        error);
                    return error;
                }
                merge = 1;
                break;

            case INI_MS_MERGE:
                /* Merge */
            default:
                TRACE_INFO_STRING("Merge mode", "");
                merge = 1;
                break;
            }

            if (merge) {
                error = merge_section(po);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to merge section", error);
                    return error;
                }
            }

            po->merge_sec = NULL;
        }
        else {
            /* Add section to configuration */
            TRACE_INFO_STRING("Now adding collection", "");
            error = col_add_collection_to_collection(po->top,
                                                     NULL, NULL,
                                                     po->sec,
                                                     COL_ADD_MODE_EMBED);

            if (error) {
                TRACE_ERROR_NUMBER("Failed to embed section", error);
                return error;
            }

            po->sec = NULL;
        }
    }

    TRACE_FLOW_EXIT();
    return EOK;

}
Esempio n. 17
0
/* Merge contents of the section */
static int merge_section(struct parser_obj *po)
{
    int error = EOK;
    struct collection_item *item = NULL;
    struct value_obj *vo = NULL;
    int work_to_do = 1;
    const char *key;

    TRACE_FLOW_ENTRY();

    do {
        TRACE_INFO_STRING("Top of the merge loop", "");

        item = NULL;
        error = col_extract_item_from_current(po->sec,
                                              COL_DSP_FRONT,
                                              NULL,
                                              0,
                                              COL_TYPE_ANY,
                                              &item);
        if ((error) && (error != ENOENT)) {
            TRACE_ERROR_NUMBER("Failed to extract item.", error);
            return error;
        }

        if (item) {

            TRACE_INFO_STRING("Item found:", col_get_item_property(item, NULL));

            if (strncmp(col_get_item_property(item, NULL),
                        INI_SECTION_KEY, 1) == 0) {
                /* Just ignore the first item */
                vo = *((struct value_obj **)(col_get_item_data(item)));
                value_destroy(vo);
                col_delete_item(item);
                continue;
            }

            po->merge_vo = *((struct value_obj **)(col_get_item_data(item)));
            key = col_get_item_property(item, NULL);
            /* To be able to use po->merge_key in the loop
             * we have to overcome constraints imposed by
             * the "const" declaration.
             */
            memcpy(&(po->merge_key), &key, sizeof(char *));

            /* Use the value processing function to inser the value */
            error = complete_value_processing(po);

            /* In case of error value is already cleaned */
            po->merge_vo = NULL;
            po->merge_key = NULL;
            col_delete_item(item);
            /* Now we can check the error */
            if (error) {
                TRACE_ERROR_NUMBER("Failed to merge item.", error);
                return error;
            }
        }
        else {
            TRACE_INFO_STRING("No more items:", "");
            work_to_do = 0;
        }
    }
    while (work_to_do);

    /* If we reached this place the incoming section is empty.
     * but just to be safe clean with callback. */
    col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
    po->sec = NULL;

    TRACE_FLOW_EXIT();
    return EOK;
}
Esempio n. 18
0
/* Clean all items in the section */
int empty_section(struct collection_item *sec)
{
    int error = EOK;
    struct collection_item *item = NULL;
    struct collection_item *save_item = NULL;
    struct value_obj *vo = NULL;
    int work_to_do = 1;

    TRACE_FLOW_ENTRY();

    do {
        item = NULL;
        error = col_extract_item_from_current(sec,
                                              COL_DSP_FRONT,
                                              NULL,
                                              0,
                                              COL_TYPE_ANY,
                                              &item);
        if ((error) && (error != ENOENT)) {
            TRACE_ERROR_NUMBER("Failed to extract item.", error);
            return error;
        }

        if (item) {
            TRACE_INFO_STRING("Item found:",
                              col_get_item_property(item, NULL));

            if (strncmp(col_get_item_property(item, NULL),
                        INI_SECTION_KEY, 1) == 0) {
                /* Just ignore the first item */
                save_item = item;
                continue;
            }

            vo = *((struct value_obj **)(col_get_item_data(item)));
            value_destroy(vo);
            col_delete_item(item);
        }
        else {
            TRACE_INFO_STRING("No more items:", "");
            /* Restore saved item */
            error = col_insert_item(sec,
                                    NULL,
                                    save_item,
                                    COL_DSP_END,
                                    NULL,
                                    0,
                                    COL_INSERT_NOCHECK);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to restore item.", error);
                return error;
            }

            work_to_do = 0;
        }
    }
    while (work_to_do);

    TRACE_FLOW_EXIT();
    return EOK;
}
Esempio n. 19
0
/* Create a copy of the value */
int value_copy(struct value_obj *vo,
               struct value_obj **copy_vo)
{

    int error = EOK;
    struct value_obj *new_vo = NULL;
    struct simplebuffer *oneline = NULL;

    TRACE_FLOW_ENTRY();

    if ((!copy_vo) || (!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,
                                 (const char *)simplebuffer_get_buf(vo->unfolded),
                                 simplebuffer_get_len(vo->unfolded),
                                 INI_VALUE_BLOCK);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to add string", error);
        simplebuffer_free(oneline);
        return error;
    }

    /* Acllocate new INI value structure */
    new_vo = malloc(sizeof(struct value_obj));
    if (!new_vo) {
        TRACE_ERROR_NUMBER("No memory", ENOMEM);
        simplebuffer_free(oneline);
        return ENOMEM;
    }

    new_vo->origin = vo->origin;
    new_vo->line = vo->line;
    new_vo->unfolded = oneline;
    new_vo->keylen = vo->keylen;
    new_vo->boundary = vo->boundary;
    new_vo->raw_lines = NULL;
    new_vo->raw_lengths = NULL;

    error = value_create_arrays(&(new_vo->raw_lines),
                                &(new_vo->raw_lengths));

    if (error) {
        TRACE_ERROR_NUMBER("Failed to fold", error);
        value_destroy(new_vo);
        return error;
    }

    /* Create arrays by folding the value */
    error = value_fold(new_vo->unfolded,
                       new_vo->keylen,
                       new_vo->boundary,
                       new_vo->raw_lines,
                       new_vo->raw_lengths);
    if (error) {
        TRACE_ERROR_NUMBER("Failed to fold", error);
        value_destroy(new_vo);
        return error;
    }

    /* Copy comment */
    if (vo->ic) {
        error = ini_comment_copy(vo->ic, &new_vo->ic);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to copy comment", error);
            value_destroy(new_vo);
            return error;
        }
    }
    else new_vo->ic = NULL;

    *copy_vo = new_vo;

    TRACE_INFO_STRING("Orig value:",
                      (const char *)simplebuffer_get_buf(vo->unfolded));
    TRACE_INFO_STRING("Copy value:",
                      (const char *)simplebuffer_get_buf(new_vo->unfolded));

    TRACE_INFO_NUMBER("Orig value num lines:",
                      ref_array_len(vo->raw_lengths));
    TRACE_INFO_NUMBER("Copy value num lines:",
                      ref_array_len(new_vo->raw_lengths));

    TRACE_FLOW_EXIT();
    return error;
}
Esempio n. 20
0
/* Function to read next line from the file */
static int parser_read(struct parser_obj *po)
{
    int error = EOK;
    char *buffer = NULL;
    ssize_t res = 0;
    size_t len = 0;
    int32_t i = 0;
    uint32_t action;

    TRACE_FLOW_ENTRY();

    /* Adjust line number */
    (po->linenum)++;

    /* Get line from the file */
    res = getline(&buffer, &len, po->file);
    if (res == -1) {
        if (feof(po->file)) {
            TRACE_FLOW_STRING("Read nothing", "");
            if (po->inside_comment) {
                action = PARSE_ERROR;
                po->last_error = ERR_BADCOMMENT;
            }
            else action = PARSE_POST;
        }
        else {
            TRACE_ERROR_STRING("Error reading", "");
            action = PARSE_ERROR;
            po->last_error = ERR_READ;
        }
        if(buffer) free(buffer);
    }
    else {
        /* Read Ok */
        len = res;
        TRACE_INFO_STRING("Read line ok:", buffer);
        TRACE_INFO_NUMBER("Length:", len);
        TRACE_INFO_NUMBER("Strlen:", strlen(buffer));

        if (buffer[0] == '\0') {
            /* Empty line - read again (should not ever happen) */
            action = PARSE_READ;
            free(buffer);
        }
        else {
            /* Check length */
            if (len >= BUFFER_SIZE) {
                TRACE_ERROR_STRING("Too long", "");
                action = PARSE_ERROR;
                po->last_error = ERR_LONGDATA;
                free(buffer);
            }
            else {
                /* Trim end line */
                i = len - 1;
                while ((i >= 0) &&
                       ((buffer[i] == '\r') ||
                        (buffer[i] == '\n'))) {
                    TRACE_INFO_NUMBER("Offset:", i);
                    TRACE_INFO_NUMBER("Code:", buffer[i]);
                    buffer[i] = '\0';
                    i--;
                }

                po->last_read = buffer;
                po->last_read_len = i + 1;
                action = PARSE_INSPECT;
                TRACE_INFO_STRING("Line:", po->last_read);
                TRACE_INFO_NUMBER("Linelen:", po->last_read_len);
            }
        }
    }

    /* 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 EOK;
}
Esempio n. 21
0
/* Serialize value */
int value_serialize(struct value_obj *vo,
                    const char *key,
                    struct simplebuffer *sbobj)
{
    int error = EOK;
    uint32_t num = 0;
    uint32_t i = 0;
    uint32_t len = 0;
    char *commentline = NULL;
    char *ptr = NULL;
    char *part = NULL;
    int sec = 0;
    uint32_t vln = 0;

    TRACE_FLOW_ENTRY();
    TRACE_INFO_STRING("Serializing key:", key);

    if (!vo) {
        TRACE_ERROR_NUMBER("Invalid input parameter", EINVAL);
        return EINVAL;
    }

    /* Put comment first */
    if (vo->ic) {

        /* Get number of lines in the comment */
        error = ini_comment_get_numlines(vo->ic, &num);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to get number of lines", errno);
            return error;
        }

        for (i = 0; i < num; i++) {

            len = 0;
            commentline = NULL;

            error = ini_comment_get_line(vo->ic, i, &commentline, &len);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to get number of lines", errno);
                return error;
            }

            error = simplebuffer_add_raw(sbobj,
                                         commentline,
                                         len,
                                         INI_VALUE_BLOCK);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add comment", error);
                return error;
            }

            error = simplebuffer_add_cr(sbobj);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add CR", error);
                return error;
            }
        }
    }

    if (strncmp(key, INI_SPECIAL_KEY, sizeof(INI_SPECIAL_KEY)) == 0) {
        /* Special key carries only a comment */
        TRACE_FLOW_EXIT();
        return EOK;
    }

    /* Handle the case it is a section key */
    if (strncmp(key,
                INI_SECTION_KEY,
                sizeof(INI_SECTION_KEY)) == 0) sec = 1;

    if (sec) {
        error = simplebuffer_add_str(sbobj,
                                     INI_OPEN_BR,
                                     sizeof(INI_OPEN_BR) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add opening section bracket", error);
            return error;

        }
    }
    else {

        error = simplebuffer_add_str(sbobj,
                                     key,
                                     vo->keylen,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add key", error);
            return error;
        }

        error = simplebuffer_add_str(sbobj,
                                     INI_EQUAL_SIGN,
                                     sizeof(INI_EQUAL_SIGN) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add equal sign", error);
            return error;
        }

    }

    if (vo->raw_lines) {

        vln = ref_array_len(vo->raw_lines);
        TRACE_INFO_NUMBER("Number of lines:", vln);

#ifdef HAVE_TRACE

extern void ref_array_debug(struct ref_array *ra, int num);

        ref_array_debug(vo->raw_lines, 0);
        ref_array_debug(vo->raw_lengths, 1);
#endif

        for (i = 0; i < vln; i++) {
            /* Get line */
            ptr = ref_array_get(vo->raw_lines, i, NULL);

            if (ptr) {
                /* Get its length */
                len = 0;
                ref_array_get(vo->raw_lengths, i, (void *)&len);

                part = *((char **)(ptr));

                TRACE_INFO_STRING("Value:", part);
                TRACE_INFO_NUMBER("Lenght:", len);

                error = simplebuffer_add_raw(sbobj,
                                             part,
                                             len,
                                             INI_VALUE_BLOCK);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to add value", error);
                    return error;
                }

            }
            if (!sec) {
                error = simplebuffer_add_cr(sbobj);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to add CR", error);
                    return error;
                }
            }
        }

        if ((!vln) && (!sec)) {
            error = simplebuffer_add_cr(sbobj);
            if (error) {
                TRACE_ERROR_NUMBER("Failed to add CR", error);
                return error;
            }
        }
    }

    if (sec) {
        error = simplebuffer_add_str(sbobj,
                                     INI_CLOSE_BR,
                                     sizeof(INI_CLOSE_BR) - 1,
                                     INI_VALUE_BLOCK);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add closing bracket", error);
            return error;

        }

        error = simplebuffer_add_cr(sbobj);
        if (error) {
            TRACE_ERROR_NUMBER("Failed to add CR", error);
            return error;
        }
    }

    TRACE_INFO_STRING("Buffer:", (const char *)simplebuffer_get_buf(sbobj));
    TRACE_FLOW_EXIT();
    return error;
}
Esempio n. 22
0
/* Function to create a folded value out of the unfolded string */
static int value_fold(struct simplebuffer *unfolded,
                      uint32_t key_len,
                      uint32_t fold_bound,
                      struct ref_array *raw_lines,
                      struct ref_array *raw_lengths)
{
    int error = EOK;
    const char *buf;
    uint32_t len = 0;          /* Full length of the buffer          */
    uint32_t fold_place = 0;   /* Potential folding place            */
    uint32_t best_place = 0;   /* Dynamic folding boundary           */
    uint32_t next_place = 0;   /* Position of the found space        */
    uint32_t fold_len = 0;     /* Determined length of the substring */
    uint32_t idx = 0;          /* Counter of lines                   */
    uint32_t i = 0;            /* Internal counter                   */
    uint32_t resume_place = 0; /* Place we resume parsing            */
    uint32_t start_place = 0;  /* Start of the string                */
    int done = 0;              /* Are we done?                       */

    TRACE_FLOW_ENTRY();

    /* Reset arrays */
    ref_array_reset(raw_lines);
    ref_array_reset(raw_lengths);

    /* Get the buffer info */
    len = simplebuffer_get_len(unfolded);
    if (!len) {
        /* Nothing to fold */
        TRACE_FLOW_EXIT();
        return EOK;
    }

    buf = (const char *)simplebuffer_get_buf(unfolded);

    TRACE_INFO_STRING("Unfolded value:", buf);

    /* Make sure that we have at least one character to fold */
    if (fold_bound == 0) fold_bound++;

    while (!done) {
        /* Determine the max length of the line */
        if (idx == 0) {
             if (fold_bound > (key_len + INI_FOLDING_OVERHEAD)) {
                 best_place = fold_bound - key_len - INI_FOLDING_OVERHEAD;
             }
             else best_place = 0;
        }
        else {
             best_place = fold_bound;

             /* Starting with the second line if we plan
              * to add space ourselves factor it into folding
              * boadary
              */
             if ((buf[start_place] != ' ') &&
                 (buf[start_place] != '\t')) best_place--;
        }

        TRACE_INFO_NUMBER("Best place", best_place);

        fold_place = start_place;
        next_place = start_place;
        best_place += start_place;


        /* Parse the buffer from the right place */
        for (i = resume_place; i <= len; i++) {

            /* Check for folding opportunity */
            if (i == len) {
                next_place = i;
                done = 1;
            }
            /*
             * Fold if we found the separator or the first line
             * is too long right away
             */
            else if (((buf[i] == ' ') || (buf[i] == '\t')) ||
                     ((best_place == 0) && (i == 0))) {
                next_place = i;
                TRACE_INFO_NUMBER("Next place:", next_place);
            }
            else continue;

            if ((next_place > best_place) || (next_place == 0)) {
                if ((fold_place == start_place) &&
                    (next_place != 0)) {
                    /* Our first found folding place
                     * is already after the preferred
                     * folding place. Time to fold then...
                     */
                    fold_len = next_place - start_place;

                }
                else {
                    /* We will use the previous
                     * folding place.
                     */
                    fold_len = fold_place - start_place;

                }

                TRACE_INFO_NUMBER("Fold len:", fold_len);

                error = save_portion(raw_lines,
                                     raw_lengths,
                                     buf + start_place,
                                     fold_len);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to save", error);
                    return error;
                }

                start_place += fold_len;

                /*
                 * This will force the re-processing
                 * of the same space but it is
                 * helpful in case the middle portion
                 * of the value is beyond our folding limit.
                 */
                resume_place = next_place;
                if (fold_len == 0) resume_place++;
                idx++;
                break;
            }
            else { /* Case when next_place <= best_place */
                fold_place = next_place;
            }
        }

        /* Save last portion */
        if (done) {
            if (next_place - start_place) {
                error = save_portion(raw_lines,
                                     raw_lengths,
                                     buf + start_place,
                                     next_place - start_place);
                if (error) {
                    TRACE_ERROR_NUMBER("Failed to save last chunk", error);
                    return error;
                }
                idx++;
            }
        }
    }

    TRACE_FLOW_EXIT();
    return error;
}