int main(int argc, char const *argv[])
{
  
  TreeNode nodes[] = {
    TreeNode(1), // 0
    TreeNode(2), TreeNode(2),  // 1, 2
    TreeNode(3), TreeNode(3),  // 3, 4
    TreeNode(4), TreeNode(4),  // 5, 6
  };
  nodes[0].left = &nodes[1];
  nodes[0].right = &nodes[2];
  nodes[1].left = &nodes[3];
  nodes[1].right = &nodes[5];
  nodes[2].left = &nodes[6];
  nodes[2].right = &nodes[4];

  TreeNode *root = &nodes[0];
  preorder_cout(root);

  serialize_tree("tmp.txt", root);
  TreeNode *read = deserialize_tree("tmp.txt");
  preorder_cout(read);

  read = deserialize_tree(string("1 2 # # 3 4 # 5 # #"));
  preorder_cout(read);
  inorder_cout(read);
  return 0;
}
Example #2
0
int kowhai_serialize_tree(struct kowhai_tree_t tree, char* target_buffer, int* target_size, void* get_name_param, kowhai_get_symbol_name_t get_name)
{
    int largest_data_field;
    int chars = serialize_tree(&tree.desc, &tree.data, target_buffer, *target_size, 0, get_name_param, get_name, tree.desc->type == KOW_BRANCH_U_START, &largest_data_field);
    if (chars < 0)
        return KOW_STATUS_TARGET_BUFFER_TOO_SMALL;
    *target_size = chars;
    return KOW_STATUS_OK;
}
Example #3
0
int serialize_tree(struct kowhai_node_t** desc, void** data, char* target_buffer, size_t target_size, int level, void* get_name_param, kowhai_get_symbol_name_t get_name, int in_union, int* largest_data_field)
{
    int target_offset = 0;
    struct kowhai_node_t* node;
    int i, chars;
    char* node_end_str;

    while (1)
    {
        node = *desc;

        if (node->type == KOW_BRANCH_END)
            return target_offset;

        // indent to current level using tabs
        chars = add_indent(&target_buffer, &target_size, &target_offset, level);
        if (chars < 0)
            return chars;

        //
        // write node
        //

        switch (node->type)
        {
            case KOW_BRANCH_START:
            case KOW_BRANCH_U_START:
            {
                int node_is_union = node->type == KOW_BRANCH_U_START;
                int largest_child_data_field = 0;
                void* initial_data = *data;
                // write header
                chars = add_header(&target_buffer, &target_size, &target_offset, node, get_name_param, get_name);
                if (chars < 0)
                    return chars;
                if (node->count > 1)
                {
                    struct kowhai_node_t* initial_node = *desc;
                    // write array identifier
                    chars = add_string(&target_buffer, &target_size, &target_offset, ", \""ARRAY"\": [\n");
                    if (chars < 0)
                    return chars;
                    for (i = 0; i < node->count; i++)
                    {
                        // set descriptor to initial node at the branch array
                        *desc = initial_node;
                        (*desc) += 1;
                        // indent to current level using tab
                        chars = add_indent(&target_buffer, &target_size, &target_offset, level + 1);
                        if (chars < 0)
                            return chars;
                        // write branch children start
                        chars = add_string(&target_buffer, &target_size, &target_offset, "[\n");
                        if (chars < 0)
                            return chars;
                        // write branch children
                        chars = serialize_tree(desc, data, target_buffer, target_size, level + 1, get_name_param, get_name, node_is_union, &largest_child_data_field);
                        if (chars < 0)
                            return chars;
                        target_offset += chars;
                        target_buffer += chars;
                        target_size -= chars;
                        // increment data pointer if node is a union
                        if (node_is_union)
                        {
                            *data = (char*)initial_data + largest_child_data_field;
                            initial_data = *data;
                        }
                        // indent to current level using tab
                        chars = add_indent(&target_buffer, &target_size, &target_offset, level + 1);
                        if (chars < 0)
                            return chars;
                        // write branch children end
                        chars = add_string(&target_buffer, &target_size, &target_offset, "]");
                        if (chars < 0)
                            return chars;
                        if (i < node->count - 1)
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, ",\n");
                            if (chars < 0)
                                return chars;
                        }
                        else
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, "\n");
                            if (chars < 0)
                                return chars;
                        }
                    }
                }
                else
                {
                    // write children identifier
                    chars = add_string(&target_buffer, &target_size, &target_offset, ", \""CHILDREN"\": [\n");
                    if (chars < 0)
                        return chars;
                    // write branch children
                    (*desc) += 1;
                    chars = serialize_tree(desc, data, target_buffer, target_size, level + 1, get_name_param, get_name, node_is_union, &largest_child_data_field);
                    if (chars < 0)
                        return chars;
                    target_offset += chars;
                    target_buffer += chars;
                    target_size -= chars;
                    // increment data pointer if node is a union
                    if (node_is_union)
                        *data = (char*)initial_data + largest_child_data_field;
                }
                // indent to current level using tab
                chars = add_indent(&target_buffer, &target_size, &target_offset, level);
                if (chars < 0)
                    return chars;
                // write node end
                if (level == 0 || (*desc)[1].type == KOW_BRANCH_END)
                    node_end_str = "]}\n";
                else
                    node_end_str = "]},\n";
                chars = add_string(&target_buffer, &target_size, &target_offset, node_end_str);
                if (chars < 0)
                    return chars;
                break;
            }
            default:
            {
                int value_size = kowhai_get_node_type_size(node->type);
                // write header
                chars = add_header(&target_buffer, &target_size, &target_offset, node, get_name_param, get_name);
                if (chars < 0)
                    return chars;
                // write value identifier
                chars = add_string(&target_buffer, &target_size, &target_offset, ", \""VALUE"\": ");
                if (chars < 0)
                    return chars;
                // write value/s
                if (node->type == KOW_CHAR && node->count > 1 && str_printable((char *)*data, node->count))
                {
                    // special string case
                    chars = write_string(target_buffer, target_size, "\"%.*s\"", node->count, (char*)*data);
                    if (chars >= 0)
                    {
                        target_buffer += chars;
                        target_size -= chars;
                        target_offset += chars;
                    }
                    else
                        return chars;
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size * node->count;
                    else if (value_size * node->count > *largest_data_field)
                        *largest_data_field = value_size * node->count;
                }
                else if (node->count > 1)
                {
                    // write start bracket
                    chars = add_string(&target_buffer, &target_size, &target_offset, "[");
                    if (chars < 0)
                        return chars;
                    for (i = 0; i < node->count; i++)
                    {
                        // write leaf node array item value
                        chars = add_value(&target_buffer, &target_size, &target_offset, node->type, (char*)*data + i * value_size);
                        if (chars < 0)
                            return chars;
                        // write comma if there is another array item
                        if (i < node->count - 1)
                        {
                            chars = add_string(&target_buffer, &target_size, &target_offset, ", ");
                            if (chars < 0)
                                return chars;
                        }
                    }
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size * node->count;
                    else if (value_size * node->count > *largest_data_field)
                        *largest_data_field = value_size * node->count;
                    // write end bracket
                    chars = add_string(&target_buffer, &target_size, &target_offset, "]");
                    if (chars < 0)
                        return chars;
                }
                else
                {
                    // write leaf node value
                    chars = add_value(&target_buffer, &target_size, &target_offset, node->type, *data);
                    if (chars < 0)
                        return chars;
                    // increment data pointer
                    if (!in_union)
                        *data = (char*)*data + value_size;
                    else if (value_size > *largest_data_field)
                        *largest_data_field = value_size;
                }
                // write node end
                if (level == 0 || node[1].type == KOW_BRANCH_END)
                    node_end_str = " }\n";
                else
                    node_end_str = " },\n";
                chars = add_string(&target_buffer, &target_size, &target_offset, node_end_str);
                if (chars < 0)
                    return chars;
                break;
            }
        }

        if (level == 0)
            return target_offset;

        (*desc) += 1;
    }
}