feisty meow concerns codebase 2.140
infoton.cpp
Go to the documentation of this file.
1/*****************************************************************************\
2* *
3* Name : infoton *
4* Author : Chris Koeritz *
5* *
6*******************************************************************************
7* Copyright (c) 2002-$now By Author. This program is free software; you can *
8* redistribute it and/or modify it under the terms of the GNU General Public *
9* License as published by the Free Software Foundation; either version 2 of *
10* the License or (at your option) any later version. This is online at: *
11* http://www.fsf.org/copyleft/gpl.html *
12* Please send any updates to: fred@gruntose.com *
13\*****************************************************************************/
14
15#include "infoton.h"
16
17#include <basis/functions.h>
22
23using namespace basis;
24using namespace loggers;
25using namespace structures;
26using namespace textual;
27
28namespace octopi {
29
30#undef LOG
31#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
32
33//#define DEBUG_INFOTON
34 // if uncommented, then extra checks are made.
35
37 // this single byte version number should be increased when the network
38 // protocol changes. it only ensures that the fast_pack method will reject
39 // a lower version.
40
42: _classifier(new string_array(classifier))
43{
44 FUNCDEF("constructor [string_array]");
45}
46
48: _classifier(new string_array)
49{
50 FUNCDEF("constructor [one string]");
51 *_classifier += class_1;
52}
53
54infoton::infoton(const astring &class_1, const astring &class_2)
55: _classifier(new string_array)
56{
57 FUNCDEF("constructor [two strings]");
58 *_classifier += class_1;
59 *_classifier += class_2;
60}
61
62infoton::infoton(const astring &class_1, const astring &class_2,
63 const astring &class_3)
64: _classifier(new string_array)
65{
66 FUNCDEF("constructor [three strings]");
67 *_classifier += class_1;
68 *_classifier += class_2;
69 *_classifier += class_3;
70}
71
73: root_object(),
74 packable(),
75 clonable(),
76 _classifier(new string_array(*to_copy._classifier))
77{}
78
80{ WHACK(_classifier); }
81
83{ *_classifier = *to_copy._classifier; return *this; }
84
86{ return *_classifier; }
87
88bool infoton::check_classifier(const astring &classname, const astring &caller)
89{
90 bool to_return = true;
91 if (!_classifier->length())
92 to_return = false;
93 for (int i = 0; i < _classifier->length(); i++) {
94 if (!(*_classifier)[i].length())
95 to_return = false;
96 }
97 if (!to_return) {
98 program_wide_logger::get().log(classname + "::" + caller
99 + ": invalid classifier provided.", ALWAYS_PRINT);
100 }
101 return to_return;
102}
103
104void infoton::set_classifier(const string_array &new_classifier)
105{
106#ifdef DEBUG_INFOTON
107 FUNCDEF("set_classifier [string_array]");
108#endif
109 *_classifier = new_classifier;
110#ifdef DEBUG_INFOTON
112#endif
113}
114
116{
117#ifdef DEBUG_INFOTON
118 FUNCDEF("set_classifier [1 string]");
119#endif
120 _classifier->reset();
121 *_classifier += class_1;
122#ifdef DEBUG_INFOTON
124#endif
125}
126
127void infoton::set_classifier(const astring &class_1, const astring &class_2)
128{
129#ifdef DEBUG_INFOTON
130 FUNCDEF("set_classifier [2 strings]");
131#endif
132 _classifier->reset();
133 *_classifier += class_1;
134 *_classifier += class_2;
135#ifdef DEBUG_INFOTON
137#endif
138}
139
140void infoton::set_classifier(const astring &class_1, const astring &class_2,
141 const astring &class_3)
142{
143#ifdef DEBUG_INFOTON
144 FUNCDEF("set_classifier [3 strings]");
145#endif
146 _classifier->reset();
147 *_classifier += class_1;
148 *_classifier += class_2;
149 *_classifier += class_3;
150#ifdef DEBUG_INFOTON
152#endif
153}
154
156{
157 return classifier.packed_size() // for classifier.
158 + sizeof(int) // for the package size.
159 + 1; // for the version byte.
160}
161
162void infoton::fast_pack(byte_array &packed_form, const infoton &to_pack)
163{
164 FUNCDEF("fast_pack");
166 // add the tasty version byte as the very first item.
167 structures::pack_array(packed_form, to_pack.classifier());
168 // must first put the packed infoton into a byte array, then use the
169 // byte array's packing support.
170 int len_prior = packed_form.length();
171 structures::attach(packed_form, int(0));
172 // save space for length.
173//hmmm: this could use obscure_pack for more reliability.
174 to_pack.pack(packed_form);
175 int added_len = packed_form.length() - sizeof(int) - len_prior;
176
177 // shift in the length in the place where we made space.
178 basis::un_int temp = basis::un_int(added_len);
179 for (basis::un_int i = 0; i < sizeof(int); i++) {
180 packed_form[len_prior + i] = abyte(temp % 0x100);
181 temp >>= 8;
182 }
183}
184
185bool infoton::test_fast_unpack(const byte_array &packed_form,
186 int &packed_length)
187{
188 FUNCDEF("test_fast_unpack");
189 packed_length = 0;
190 if (!packed_form.length()) return false;
191
192 // make sure we have the right version number, first.
193 if (packed_form[0] != FAST_PACK_VERSION)
194 return false;
195
196 un_int strings_held = 0;
197 byte_array len_bytes = packed_form.subarray(1, 2 * sizeof(int));
198 if (!structures::obscure_detach(len_bytes, strings_held) || !strings_held) {
199 return false;
200 }
201
202 // check through all of the strings.
203 const void *zero_posn = packed_form.observe() + sizeof(int) * 2 + 1;
204 for (int i = 0; i < (int)strings_held; i++) {
205 // locate the zero termination if possible.
206 int index = int((abyte *)zero_posn - packed_form.observe());
207 zero_posn = memchr(packed_form.observe() + index, '\0',
208 packed_form.length() - index);
209 // make sure we could find the zero termination.
210 if (!zero_posn) {
211 // nope, never saw a zero. good thing we checked.
212 return false;
213 }
214 }
215
216 // base our expected position for the data length on the position of the
217 // last string we found.
218 int datalen_start = int((abyte *)zero_posn - packed_form.observe()) + 1;
219 byte_array just_len = packed_form.subarray(datalen_start,
220 datalen_start + sizeof(int) - 1);
221 if (!structures::detach(just_len, packed_length)) return false;
222 packed_length += datalen_start + sizeof(int);
223 // include the classifier length and integer package length.
224 return true;
225}
226
227bool infoton::fast_unpack(byte_array &packed_form, string_array &classifier,
228 byte_array &info)
229{
230 FUNCDEF("fast_unpack");
232 info.reset();
233 abyte version_checking = 0;
234 if (!structures::detach(packed_form, version_checking)) return false;
235 if (version_checking != FAST_PACK_VERSION) return false;
236 if (!structures::unpack_array(packed_form, classifier)) return false;
237 int len = 0;
238 if (!structures::detach(packed_form, len)) return false;
239 if (len > packed_form.length()) {
240 // not enough data.
241 continuable_error(static_class_name(), func, "failed to have enough data!");
242 return false;
243 }
244 info = packed_form.subarray(0, len - 1);
245 packed_form.zap(0, len - 1);
246 return true;
247}
248
249} //namespace.
250
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition array.h:349
array subarray(int start, int end) const
Returns the array segment between the indices "start" and "end".
Definition array.h:443
const contents * observe() const
Returns a pointer to the underlying C array of data.
Definition array.h:172
int length() const
Returns the current reported length of the allocated C array.
Definition array.h:115
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
Definition array.h:769
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
virtual outcome log(const base_string &info, int filter)=0
writes the information in "info" to the logger using the "filter".
A very common template for a dynamic array of bytes.
Definition byte_array.h:36
A clonable object knows how to make copy of itself.
Definition contracts.h:109
A base class for objects that can pack into an array of bytes.
Definition byte_array.h:87
virtual const char * class_name() const =0
Returns the bare name of this class as a constant character pointer.
static loggers::standard_log_base & get()
Provided by the startup code within each application for logging.
An infoton is an individual request parcel with accompanying information.
Definition infoton.h:32
virtual ~infoton()
Definition infoton.cpp:79
static void fast_pack(basis::byte_array &packed_form, const infoton &to_pack)
flattens an infoton "to_pack" into the byte array "packed_form".
Definition infoton.cpp:162
infoton & operator=(const infoton &to_copy)
assigns only the base class portion.
Definition infoton.cpp:82
static bool fast_unpack(basis::byte_array &packed_form, structures::string_array &classifier, basis::byte_array &info)
undoes a previous fast_pack to restore the previous information.
Definition infoton.cpp:227
void set_classifier(const structures::string_array &new_classifier)
sets the infoton's classifier to the "new_classifier".
Definition infoton.cpp:104
const structures::string_array & classifier() const
this array of strings is the "name" for this infoton.
Definition infoton.cpp:85
bool check_classifier(const basis::astring &class_name, const basis::astring &caller)
checks that the classifier seems valid.
Definition infoton.cpp:88
static int fast_pack_overhead(const structures::string_array &classifier)
reports how much space is needed to pack the "classifier".
Definition infoton.cpp:155
infoton(const structures::string_array &classifier)
creates an infoton with the "classifier".
Definition infoton.cpp:41
static bool test_fast_unpack(const basis::byte_array &packed_form, int &packed_length)
checks that the "packed_form" could hold a valid packed infoton.
Definition infoton.cpp:185
virtual void pack(basis::byte_array &packed_form) const =0
stuffs the data in the infoton into the "packed_form".
An array of strings with some additional helpful methods.
virtual int packed_size() const
Returns the number of bytes this string array would consume if packed.
#define continuable_error(c, f, i)
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition functions.h:121
unsigned char abyte
A fairly important unit which is seldom defined...
Definition definitions.h:51
unsigned int un_int
Abbreviated name for unsigned integers.
Definition definitions.h:62
A logger that sends to the console screen using the standard output device.
const abyte FAST_PACK_VERSION
Definition infoton.cpp:36
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55
bool obscure_detach(byte_array &packed_form, un_int &to_detach)
shifts the number back and checks validity, false returned if corrupted.
void attach(byte_array &packed_form, const byte_array &to_attach)
Packs a byte_array "to_attach" into "packed_form".
bool unpack_array(basis::byte_array &packed_form, basis::array< contents > &to_unpack)
provides a way to unpack any array that stores packable objects.
void pack_array(basis::byte_array &packed_form, const basis::array< contents > &to_pack)
provides a way to pack any array that stores packable objects.
bool detach(byte_array &packed_form, byte_array &to_detach)
Unpacks a byte_array "to_detach" from "packed_form".
#define static_class_name()