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