updates to move to newer gnu-er time
[feisty_meow.git] / nucleus / library / structures / object_packers.h
1 #ifndef OBJECT_PACKERS_CLASS
2 #define OBJECT_PACKERS_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : object_packers                                                    *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1995-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/byte_array.h>
19 #include <basis/definitions.h>
20
21 namespace structures {
22
23 // the sizes in bytes of common objects.  if the compiler doesn't match these, there will
24 // probably be severe tire damage.
25 const int PACKED_SIZE_BYTE = 1;
26 const int PACKED_SIZE_INT16 = 2;
27 const int PACKED_SIZE_INT32 = 4;
28 const int PACKED_SIZE_INT64 = 8;
29
30 // these functions pack and unpack popular data types.
31
32 void attach(basis::byte_array &packed_form, bool to_attach);
33   //!< Packs a bool "to_attach" into "packed_form".
34 bool detach(basis::byte_array &packed_form, bool &to_detach);
35   //!< Unpacks a bool "to_detach" from "packed_form".
36
37 void attach(basis::byte_array &packed_form, basis::abyte to_attach);
38   //!< Packs a byte "to_attach" into "packed_form".
39 bool detach(basis::byte_array &packed_form, basis::abyte &to_detach);
40   //!< Unpacks a byte "to_detach" from "packed_form".
41
42 int packed_size(const basis::byte_array &packed_form);
43   //!< Reports the size required to pack a byte array into a byte array.
44 void attach(basis::byte_array &packed_form, const basis::byte_array &to_attach);
45   //!< Packs a byte_array "to_attach" into "packed_form".
46 bool detach(basis::byte_array &packed_form, basis::byte_array &to_detach);
47   //!< Unpacks a byte_array "to_detach" from "packed_form".
48
49 void attach(basis::byte_array &packed_form, char to_attach);
50   //!< Packs a char "to_attach" into "packed_form".
51 bool detach(basis::byte_array &packed_form, char &to_detach);
52   //!< Unpacks a char "to_detach" from "packed_form".
53
54 int packed_size(double to_pack);
55   //!< Reports how large the "to_pack" will be as a stream of bytes.
56 void attach(basis::byte_array &packed_form, double to_pack);
57   //!< Packs a double precision floating point "to_attach" into "packed_form".
58 bool detach(basis::byte_array &packed_form, double &to_unpack);
59   //!< Unpacks a double precision floating point "to_attach" from "packed_form".
60
61 void attach(basis::byte_array &packed_form, float to_pack);
62   //!< Packs a floating point "to_attach" into "packed_form".
63 bool detach(basis::byte_array &packed_form, float &to_unpack);
64   //!< Unpacks a floating point "to_attach" from "packed_form".
65
66 void attach(basis::byte_array &packed_form, int to_attach);
67   //!< Packs an integer "to_attach" into "packed_form".
68   /*!< This method and the other simple numerical storage methods use a little
69   endian ordering of the bytes.  They are platform independent with respect to
70   endianness and will reassemble the number properly on any platform. */
71 bool detach(basis::byte_array &packed_form, int &to_detach);
72   //!< Unpacks an integer "to_attach" from "packed_form".
73
74 void attach(basis::byte_array &packed_form, long int to_attach);
75   //!< Packs an integer "to_attach" into "packed_form".
76   /*!< This method and the other simple numerical storage methods use a little
77   endian ordering of the bytes.  They are platform independent with respect to
78   endianness and will reassemble the number properly on any platform. */
79 bool detach(basis::byte_array &packed_form, long int &to_detach);
80   //!< Unpacks an integer "to_attach" from "packed_form".
81
82 void obscure_attach(basis::byte_array &packed_form, basis::un_int to_attach);
83   //!< like the normal attach but shifts in some recognizable sentinel data.
84   /*!< this is slightly more sure than a simple integer attachment.  it can
85   be used to make sure upcoming data is probably a valid int. */
86 bool obscure_detach(basis::byte_array &packed_form, basis::un_int &to_detach);
87   //!< shifts the number back and checks validity, false returned if corrupted.
88
89 /*
90 void attach(basis::byte_array &packed_form, long to_attach);
91   //!< Packs a long integer "to_attach" into "packed_form".
92 bool detach(basis::byte_array &packed_form, long &to_detach);
93   //!< Unpacks a long integer "to_attach" from "packed_form".
94 */
95
96 void attach(basis::byte_array &packed_form, short to_attach);
97   //!< Packs a short integer "to_attach" into "packed_form".
98 bool detach(basis::byte_array &packed_form, short &to_detach);
99   //!< Unpacks a short integer "to_attach" from "packed_form".
100
101 void attach(basis::byte_array &packed_form, basis::un_int to_attach);
102   //!< Packs an unsigned integer "to_attach" into "packed_form".
103 bool detach(basis::byte_array &packed_form, basis::un_int &to_detach);
104   //!< Unpacks an unsigned integer "to_attach" from "packed_form".
105
106 /*
107 void attach(basis::byte_array &packed_form, basis::un_long to_attach);
108   //!< Packs an unsigned long integer "to_attach" into "packed_form".
109 bool detach(basis::byte_array &packed_form, basis::un_long &to_detach);
110   //!< Unpacks an unsigned long integer "to_attach" from "packed_form".
111 */
112
113 void attach(basis::byte_array &packed_form, basis::un_short to_attach);
114   //!< Packs an unsigned short integer "to_attach" into "packed_form".
115 bool detach(basis::byte_array &packed_form, basis::un_short &to_detach);
116   //!< Unpacks an unsigned short integer "to_attach" from "packed_form".
117
118 //////////////
119
120 // helpful template functions for packing.
121
122 //! provides a way to pack any array that stores packable objects.
123 template <class contents>
124 void pack_array(basis::byte_array &packed_form, const basis::array<contents> &to_pack) {
125   obscure_attach(packed_form, to_pack.length());
126   for (int i = 0; i < to_pack.length(); i++) to_pack[i].pack(packed_form);
127 }
128
129 //! provides a way to unpack any array that stores packable objects.
130 template <class contents>
131 bool unpack_array(basis::byte_array &packed_form, basis::array<contents> &to_unpack) {
132   to_unpack.reset();
133   basis::un_int len;
134   if (!obscure_detach(packed_form, len)) return false;
135   basis::array<contents> swappy_array(len, NULL_POINTER, to_unpack.flags());
136     // we create an array of the specified length to see if it's tenable.
137   if (!swappy_array.observe()) return false;  // failed to allocate.
138   for (int i = 0; i < (int)len; i++) {
139     if (!swappy_array[i].unpack(packed_form))
140       return false;
141   }
142   // now that we've got exactly what we want, plunk it into the result array.
143   swappy_array.swap_contents(to_unpack);
144   return true;
145 }
146
147 //! provides space estimation for the objects to be packed.
148 template <class contents>
149 int packed_size_array(const basis::array<contents> &to_pack) {
150   int to_return = sizeof(int) * 2;  // obscure version uses double int size.
151   for (int i = 0; i < to_pack.length(); i++)
152     to_return += to_pack[i].packed_size();
153   return to_return;
154 }
155
156 //! Packs flat objects into an array of bytes.
157 /*! Similar to pack above, but operates on arrays with simple
158 objects that do not support functional pack and unpack. */
159 template <class contents>
160 void pack_simple(basis::byte_array &packed_form, const basis::array<contents> &to_pack) {
161   obscure_attach(packed_form, to_pack.length());
162   for (int i = 0; i < to_pack.length(); i++)
163     attach(packed_form, to_pack[i]);
164 }
165
166 //! Unpacks flat objects from an array of bytes.
167 /*! Similar to unpack above, but operates on arrays with simple
168 objects that do not support functional pack and unpack. */
169 template <class contents>
170 bool unpack_simple(basis::byte_array &packed_form, basis::array<contents> &to_unpack) {
171   to_unpack.reset();
172   basis::un_int len;
173   if (!obscure_detach(packed_form, len)) return false;
174   basis::array<contents> swappy_array(len, NULL_POINTER, to_unpack.flags());
175   if (!swappy_array.observe()) return false;  // failed to allocate.
176   for (int i = 0; i < len; i++) {
177     if (!detach(packed_form, swappy_array[i]))
178       return false;
179   }
180   swappy_array.swap_contents(to_unpack);
181   return true;
182 }
183
184 } // namespace
185
186 #endif
187