00001 #ifndef PACKABLE_IMPLEMENTATION_FILE
00002 #define PACKABLE_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "function.h"
00019 #include "packable.h"
00020
00021 #include <math.h>
00022
00023 packable::~packable() {}
00024
00025 int packable::packed_size() const { return 0; }
00026
00027 namespace basis {
00028
00029
00030
00031 void rotate_in(byte_array &attach_into, int to_attach, int size_in_bytes)
00032 {
00033 u_int temp = u_int(to_attach);
00034 for (int i = 0; i < size_in_bytes; i++) {
00035 attach_into += byte(temp % 0x100);
00036 temp >>= 8;
00037 }
00038 }
00039
00040 void snag_out(byte_array &eat_from, u_int &accumulator, int size_in_bytes)
00041 {
00042 accumulator = 0;
00043 for (int i = 0; i < size_in_bytes; i++) {
00044 accumulator <<= 8;
00045 accumulator += eat_from[size_in_bytes - i - 1];
00046 }
00047 eat_from.zap(0, size_in_bytes - 1);
00048 }
00049
00051
00052 int packed_size(byte_array &packed_form)
00053 { return 2 * sizeof(int) + packed_form.length(); }
00054
00055 void attach(byte_array &packed_form, const byte_array &to_attach)
00056 {
00057 obscure_attach(packed_form, to_attach.length());
00058 packed_form += to_attach;
00059 }
00060
00061 bool detach(byte_array &packed_form, byte_array &to_detach)
00062 {
00063 int len = 0;
00064 if (!obscure_detach(packed_form, len)) return false;
00065 if (packed_form.length() < len) return false;
00066 to_detach = packed_form.subarray(0, len - 1);
00067 packed_form.zap(0, len - 1);
00068 return true;
00069 }
00070
00072
00073
00074
00075
00076 void attach(byte_array &packed_form, u_int to_attach)
00077 { rotate_in(packed_form, to_attach, 4); }
00078
00079 bool detach(byte_array &packed_form, u_int &to_detach)
00080 {
00081 if (packed_form.length() < 4) return false;
00082 u_int temp;
00083 snag_out(packed_form, temp, 4);
00084 to_detach = u_int(temp);
00085 return true;
00086 }
00087
00088 void attach(byte_array &packed_form, u_short to_attach)
00089 { rotate_in(packed_form, to_attach, 2); }
00090
00091 bool detach(byte_array &packed_form, u_short &to_detach)
00092 {
00093 if (packed_form.length() < 2) return false;
00094 u_int temp;
00095 snag_out(packed_form, temp, 2);
00096 to_detach = u_short(temp);
00097 return true;
00098 }
00099
00100 void attach(byte_array &packed_form, byte to_attach)
00101 { packed_form += to_attach; }
00102
00103 bool detach(byte_array &packed_form, byte &to_detach)
00104 {
00105 if (packed_form.length() < 1) return false;
00106 to_detach = packed_form[0];
00107 packed_form.zap(0, 0);
00108 return true;
00109 }
00110
00112
00113 void attach(byte_array &packed_form, int to_attach)
00114 { attach(packed_form, u_int(to_attach)); }
00115
00116 bool detach(byte_array &packed_form, int &to_detach)
00117 { return detach(packed_form, (u_int &)to_detach); }
00118
00119 void attach(byte_array &packed_form, u_long to_attach)
00120 { attach(packed_form, u_int(to_attach)); }
00121
00122 bool detach(byte_array &packed_form, u_long &to_detach)
00123 { return detach(packed_form, (u_int &)to_detach); }
00124
00125 void attach(byte_array &packed_form, long to_attach)
00126 { attach(packed_form, u_int(to_attach)); }
00127
00128 bool detach(byte_array &packed_form, long &to_detach)
00129 { return detach(packed_form, (u_int &)to_detach); }
00130
00131 void attach(byte_array &packed_form, short to_attach)
00132 { attach(packed_form, u_short(to_attach)); }
00133
00134 bool detach(byte_array &packed_form, short &to_detach)
00135 { return detach(packed_form, (u_short &)to_detach); }
00136
00137 void attach(byte_array &packed_form, char to_attach)
00138 { attach(packed_form, byte(to_attach)); }
00139
00140 bool detach(byte_array &packed_form, char &to_detach)
00141 { return detach(packed_form, (byte &)to_detach); }
00142
00143 void attach(byte_array &packed_form, bool to_attach)
00144 { attach(packed_form, byte(to_attach)); }
00145
00146 void attach(byte_array &packed_form, const char *to_attach)
00147 {
00148 const int len = int(strlen(to_attach));
00149 const int old_pos = packed_form.last();
00150 packed_form.insert(old_pos + 1, len + 1);
00151 memory_assign((char *)packed_form.observe() + old_pos + 1, to_attach,
00152 len + 1);
00153 }
00154
00155 bool detach(byte_array &packed_form, istring &to_detach)
00156 {
00157 if (!packed_form.length()) return false;
00158
00159 const void *zero_posn = memchr(packed_form.observe(), '\0',
00160 packed_form.length());
00161
00162 if (!zero_posn) {
00163
00164 to_detach.reset();
00165 return false;
00166 }
00167
00168
00169 to_detach = (char *)packed_form.observe();
00170
00171
00172 int find_len = int((byte *)zero_posn - packed_form.observe());
00173
00174 packed_form.zap(0, find_len);
00175 return true;
00176 }
00177
00179
00180
00181
00182 bool detach(byte_array &packed_form, bool &to_detach)
00183 {
00184 byte chomp;
00185 if (!detach(packed_form, chomp)) return false;
00186 to_detach = !!chomp;
00187 return true;
00188 }
00189
00190
00191
00192 inline double break_off_digit(double &input) {
00193
00194 input *= 10.0;
00195
00196 double mod_part = fmod(input, 1.0);
00197
00198 double to_return = input - mod_part;
00199
00200 input -= to_return;
00201 return to_return;
00202 }
00203
00204 void attach(byte_array &packed_form, double to_pack)
00205 {
00206 int exponent = 0;
00207 double mantissa = frexp(to_pack, &exponent);
00208 byte pos = mantissa < 0.0? false : true;
00209 mantissa = fabs(mantissa);
00210
00211 packed_form += pos;
00212 attach(packed_form, exponent);
00213 byte_array mantis;
00214
00215
00216
00217 for (int i = 0; i < 9; i++) {
00218 double dig1 = break_off_digit(mantissa);
00219
00220 double dig2 = break_off_digit(mantissa);
00221
00222 mantis += byte(dig1 * 16 + dig2);
00223 }
00224 attach(packed_form, mantis);
00225
00226 }
00227
00228 bool detach(byte_array &packed_form, double &to_unpack)
00229 {
00230
00231 if (packed_form.length() < 1) return false;
00232 byte pos = packed_form[0];
00233
00234 packed_form.zap(0, 0);
00235 int exponent;
00236 if (!detach(packed_form, exponent)) return false;
00237
00238 byte_array mantis;
00239 if (!detach(packed_form, mantis)) return false;
00240 double mantissa = 0;
00241 for (int i = mantis.last(); i >= 0; i--) {
00242 byte chop = mantis[i];
00243 double dig1 = chop / 16;
00244
00245 double dig2 = chop % 16;
00246
00247 mantissa += dig2;
00248 mantissa /= 10;
00249 mantissa += dig1;
00250 mantissa /= 10;
00251 }
00252
00253 to_unpack = ldexp(mantissa, exponent);
00254 if (!pos) to_unpack = -1.0 * to_unpack;
00255
00256
00257
00258 return true;
00259 }
00260
00261 void attach(byte_array &packed_form, float to_pack)
00262 { attach(packed_form, double(to_pack)); }
00263
00264 bool detach(byte_array &packed_form, float &to_unpack)
00265 {
00266 double real_unpack;
00267 bool to_return = detach(packed_form, real_unpack);
00268 to_unpack = (float)real_unpack;
00269 return to_return;
00270 }
00271
00273
00274 void obscure_attach(byte_array &packed_form, int to_attach)
00275 {
00276
00277 u_int first_part = 0xfade0000;
00278
00279 u_int second_part = 0x0000ce0f;
00280
00281 first_part = first_part | (to_attach & 0x0000ffff);
00282
00283 second_part = second_part | (to_attach & 0xffff0000);
00284
00285 attach(packed_form, first_part);
00286 attach(packed_form, second_part);
00287 }
00288
00289 bool obscure_detach(byte_array &packed_form, int &to_detach)
00290 {
00291 u_int first_part;
00292 u_int second_part;
00293 if (!detach(packed_form, first_part)) return false;
00294 if (!detach(packed_form, second_part)) return false;
00295
00296
00297 if (u_int(first_part & 0xffff0000) != u_int(0xfade0000)) return false;
00298
00299 if (u_int(second_part & 0x0000ffff) != u_int(0x0000ce0f)) return false;
00300
00301 to_detach = int( (second_part & 0xffff0000) + (first_part & 0x0000ffff) );
00302
00303 return true;
00304 }
00305
00307
00308 }
00309
00310
00311 #endif //PACKABLE_IMPLEMENTATION_FILE
00312