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; }
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; }
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; } }