23 using namespace basis;
30 #ifdef DEBUG_PACKABLE_TREE
32 #define LOG(to_print) printf("%s\n", astring(to_print).s());
34 #define LOG(s) { if (!!s) {} }
48 packable_tree_factory::~packable_tree_factory() {}
53 struct tree_command_unit :
public virtual packable
59 virtual ~tree_command_unit() {}
64 attach(packed_form,
int(command));
65 attach(packed_form, number);
71 if (!
detach(packed_form, cmd))
return false;
73 if (!
detach(packed_form, number))
return false;
74 if (!
detach(packed_form, size))
return false;
81 packable_tree::packable_tree() :
tree() {}
83 void packable_tree::calcit(
int &size_accumulator,
const packable_tree *current_node)
86 #ifdef DEBUG_PACKABLE_TREE
90 tree_command_unit temp;
91 size_accumulator += current_node->
packed_size() + temp.packed_size();
92 #ifdef DEBUG_PACKABLE_TREE
97 void packable_tree::packit(
byte_array &packed_form,
const packable_tree *current_node)
106 int guess = current_node->packed_size();
108 current_node->pack(temp_store);
110 if (temp_store.
length() != guess)
111 throw_error(current_node->class_name(), func,
"failure calculating size");
113 tree_command_unit command;
114 command.size = temp_store.
length();
116 if (current_node->branches() == 0) {
122 command.number = current_node->branches();
125 command.pack(packed_form);
127 packed_form += temp_store;
137 tree_command_unit end_command;
138 accum += end_command.packed_size();
146 packit(packed_form, curr);
148 tree_command_unit end_command;
149 end_command.number = 1;
150 end_command.command =
FINISH;
151 end_command.size = 0;
153 end_command.pack(packed_form);
160 tree_command_unit cmd;
162 if (!cmd.unpack(packed_form)) {
168 bool failure =
false;
172 while (cmd.command !=
FINISH) {
173 new_branch = creator.
create();
175 new_branch->
unpack(packed_form);
178 if (cmd.number > accumulated_trees.
size()) {
183 for (
int i = cmd.number; i > 0; i--) {
185 [accumulated_trees.
size()-i];
186 new_branch->
attach(to_add);
189 for (
int j = 0; j < cmd.number; j++)
191 accumulated_trees.
push(new_branch);
193 accumulated_trees.
push(new_branch);
199 if (!cmd.unpack(packed_form)) {
206 if (accumulated_trees.
size() != 1) {
209 }
else if (!failure) {
219 if (ret == common::IS_EMPTY)
break;
220 if (to_whack != new_branch)
a_sprintf is a specialization of astring that provides printf style support.
int length() const
Returns the current reported length of the allocated C array.
A very common template for a dynamic array of bytes.
Outcomes describe the state of completion for an operation.
A base class for objects that can pack into an array of bytes.
virtual int packed_size() const =0
Estimates the space needed for the packed structure.
virtual bool unpack(byte_array &packed_form)=0
Restores the packable from the "packed_form".
virtual packable_tree * create()=0
a tree factory is needed when we are recreating the packed tree.
A tree object that can be packed into an array of bytes and unpacked again.
void recursive_pack(basis::byte_array &packed_form) const
packs the whole tree starting at this node into the packed form.
int recursive_packed_size() const
spiders the tree starting at this node to calculate the packed size.
static packable_tree * recursive_unpack(basis::byte_array &packed_form, packable_tree_factory &creator)
unpacks a tree stored in "packed_form" and returns it.
A dynamically linked tree with an arbitrary number of branches.
virtual void attach(tree *new_branch)
Attaches the specified branch to the current tree.
iterator start(traversal_directions direction) const
Returns a fresh iterator positioned at this tree node.
An abstraction that represents a stack data structure.
basis::outcome push(const contents &element)
Enters a new element onto the top of the stack.
basis::outcome acquire_pop(contents &to_stuff)
Used to grab the top off of the stack.
int size() const
returns the size of the stack.
#define NULL_POINTER
The value representing a pointer to nothing.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
void attach(byte_array &packed_form, const char *to_attach)
Packs a character string "to_attach" into "packed_form".
void throw_error(const base_string &class_name, const base_string &func_name, const base_string &error_message)
throws an error that incorporates the class name and function name.
bool detach(byte_array &packed_form, astring &to_detach)
Unpacks a character string "to_attach" from "packed_form".
A dynamic container class that holds any kind of object via pointers.
bool unpack(basis::byte_array &packed_form, set< contents > &to_unpack)
provides a way to unpack any set that stores packable objects.
void pack(basis::byte_array &packed_form, const set< contents > &to_pack)
provides a way to pack any set that stores packable objects.
const int PACKED_SIZE_INT32
int packed_size(const byte_array &packed_form)
Reports the size required to pack a byte array into a byte array.
#define static_class_name()