00001 #ifndef INFOTON_IMPLEMENTATION_FILE
00002 #define INFOTON_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "infoton.h"
00019
00020 #include <basis/function.h>
00021 #include <basis/log_base.h>
00022 #include <basis/string_array.h>
00023 #include <textual/byte_format.h>
00024
00025 #undef LOG
00026 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00027
00028
00029
00030
00031 const byte FAST_PACK_VERSION = 0x14;
00032
00033
00034
00035
00036 infoton::infoton(const string_array &classifier)
00037 : _classifier(new string_array(classifier))
00038 {
00039 FUNCDEF("constructor [string_array]");
00040 }
00041
00042 infoton::infoton(const istring &class_1)
00043 : _classifier(new string_array)
00044 {
00045 FUNCDEF("constructor [one string]");
00046 *_classifier += class_1;
00047 }
00048
00049 infoton::infoton(const istring &class_1, const istring &class_2)
00050 : _classifier(new string_array)
00051 {
00052 FUNCDEF("constructor [two strings]");
00053 *_classifier += class_1;
00054 *_classifier += class_2;
00055 }
00056
00057 infoton::infoton(const istring &class_1, const istring &class_2,
00058 const istring &class_3)
00059 : _classifier(new string_array)
00060 {
00061 FUNCDEF("constructor [three strings]");
00062 *_classifier += class_1;
00063 *_classifier += class_2;
00064 *_classifier += class_3;
00065 }
00066
00067 infoton::infoton(const infoton &to_copy)
00068 : object_base(),
00069 packable(),
00070 clonable(),
00071 _classifier(new string_array(*to_copy._classifier))
00072 {}
00073
00074 infoton::~infoton()
00075 { WHACK(_classifier); }
00076
00077 infoton &infoton::operator = (const infoton &to_copy)
00078 { *_classifier = *to_copy._classifier; return *this; }
00079
00080 const string_array &infoton::classifier() const
00081 { return *_classifier; }
00082
00083 bool infoton::check_classifier(const istring &classname, const istring &caller)
00084 {
00085 bool to_return = true;
00086 if (!_classifier->length())
00087 to_return = false;
00088 for (int i = 0; i < _classifier->length(); i++) {
00089 if (!(*_classifier)[i].length())
00090 to_return = false;
00091 }
00092 if (!to_return) {
00093 program_wide_logger().log(classname + "::" + caller
00094 + ": invalid classifier provided.");
00095 }
00096 return to_return;
00097 }
00098
00099 void infoton::set_classifier(const string_array &new_classifier)
00100 {
00101 FUNCDEF("set_classifier [string_array]");
00102 *_classifier = new_classifier;
00103 #ifdef DEBUG_INFOTON
00104 check_classifier(class_name(), func);
00105 #endif
00106 }
00107
00108 void infoton::set_classifier(const istring &class_1)
00109 {
00110 FUNCDEF("set_classifier [1 string]");
00111 _classifier->reset();
00112 *_classifier += class_1;
00113 #ifdef DEBUG_INFOTON
00114 check_classifier(class_name(), func);
00115 #endif
00116 }
00117
00118 void infoton::set_classifier(const istring &class_1, const istring &class_2)
00119 {
00120 FUNCDEF("set_classifier [2 strings]");
00121 _classifier->reset();
00122 *_classifier += class_1;
00123 *_classifier += class_2;
00124 #ifdef DEBUG_INFOTON
00125 check_classifier(class_name(), func);
00126 #endif
00127 }
00128
00129 void infoton::set_classifier(const istring &class_1, const istring &class_2,
00130 const istring &class_3)
00131 {
00132 FUNCDEF("set_classifier [3 strings]");
00133 _classifier->reset();
00134 *_classifier += class_1;
00135 *_classifier += class_2;
00136 *_classifier += class_3;
00137 #ifdef DEBUG_INFOTON
00138 check_classifier(class_name(), func);
00139 #endif
00140 }
00141
00142 int infoton::fast_pack_overhead(const string_array &classifier)
00143 {
00144 return classifier.packed_size()
00145 + sizeof(int)
00146 + 1;
00147 }
00148
00149 void infoton::fast_pack(byte_array &packed_form, const infoton &to_pack)
00150 {
00151 FUNCDEF("fast_pack");
00152 basis::attach(packed_form, FAST_PACK_VERSION);
00153
00154 basis::pack(packed_form, to_pack.classifier());
00155
00156
00157 int len_prior = packed_form.length();
00158 basis::attach(packed_form, int(0));
00159
00160
00161 to_pack.pack(packed_form);
00162 int added_len = packed_form.length() - sizeof(int) - len_prior;
00163
00164
00165 u_int temp = u_int(added_len);
00166 for (u_int i = 0; i < sizeof(int); i++) {
00167 packed_form[len_prior + i] = byte(temp % 0x100);
00168 temp >>= 8;
00169 }
00170 }
00171
00172 bool infoton::test_fast_unpack(const byte_array &packed_form,
00173 int &packed_length)
00174 {
00175 FUNCDEF("test_fast_unpack");
00176 packed_length = 0;
00177 if (!packed_form.length()) return false;
00178
00179
00180 if (packed_form[0] != FAST_PACK_VERSION)
00181 return false;
00182
00183 int strings_held = 0;
00184 byte_array len_bytes = packed_form.subarray(1, 2 * sizeof(int));
00185 if (!basis::obscure_detach(len_bytes, strings_held) || !strings_held) {
00186 return false;
00187 }
00188
00189
00190 const void *zero_posn = packed_form.observe() + sizeof(int) * 2 + 1;
00191 for (int i = 0; i < strings_held; i++) {
00192
00193 int index = int((byte *)zero_posn - packed_form.observe());
00194 zero_posn = memchr(packed_form.observe() + index, '\0',
00195 packed_form.length() - index);
00196
00197 if (!zero_posn) {
00198
00199 return false;
00200 }
00201 }
00202
00203
00204
00205 int datalen_start = int((byte *)zero_posn - packed_form.observe()) + 1;
00206 byte_array just_len = packed_form.subarray(datalen_start,
00207 datalen_start + sizeof(int) - 1);
00208 if (!basis::detach(just_len, packed_length)) return false;
00209 packed_length += datalen_start + sizeof(int);
00210
00211 return true;
00212 }
00213
00214 bool infoton::fast_unpack(byte_array &packed_form, string_array &classifier,
00215 byte_array &info)
00216 {
00217 FUNCDEF("fast_unpack");
00218 classifier.reset();
00219 info.reset();
00220 byte version_checking = 0;
00221 if (!basis::detach(packed_form, version_checking)) return false;
00222 if (version_checking != FAST_PACK_VERSION) return false;
00223 if (!basis::unpack(packed_form, classifier)) return false;
00224 int len = 0;
00225 if (!basis::detach(packed_form, len)) return false;
00226 if (len > packed_form.length()) {
00227
00228 continuable_error(static_class_name(), func, "failed to have enough data!");
00229 return false;
00230 }
00231 info = packed_form.subarray(0, len - 1);
00232 packed_form.zap(0, len - 1);
00233 return true;
00234 }
00235
00236
00237 #endif //INFOTON_IMPLEMENTATION_FILE
00238