1 #ifndef BYTE_ARRAY_CLASS
2 #define BYTE_ARRAY_CLASS
4 /*****************************************************************************\
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 1991-$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 \*****************************************************************************/
19 #include "base_string.h"
20 #include "contracts.h"
21 #include "definitions.h"
23 #include <string.h> // for memcmp.
27 //! A very common template for a dynamic array of bytes.
29 byte_array provides a simple wrapper around array<byte>, but with the
30 exponential growth and simple copy modes automatically enabled.
31 Note that it is almost always best to forward declare byte_arrays in ones
32 own headers rather than including this header.
35 class byte_array : public array<abyte>, public virtual orderable
38 byte_array(int number = 0, const abyte *initial_contents = NULL_POINTER)
39 : array<abyte>(number, initial_contents, SIMPLE_COPY | EXPONE) {}
40 //!< constructs an array of "number" bytes from "initial_contents".
42 byte_array(const byte_array &to_copy)
43 : root_object(), array<abyte>(to_copy) {}
44 //!< constructs an array bytes by copying the "to_copy" array.
46 byte_array(const array<abyte> &to_copy) : array<abyte>(to_copy) {}
47 //!< constructs an array bytes by copying the "to_copy" array.
49 virtual ~byte_array() {}
51 DEFINE_CLASS_NAME("byte_array");
53 //!< returns an array of zero bytes.
54 /*!< note that this is implemented in the opsystem library to avoid bad
55 issues with static objects mixed into multiple dlls from a static
57 static const byte_array &empty_array()
58 { static byte_array g_empty; return g_empty; }
60 // these implement the orderable and equalizable interfaces.
61 virtual bool equal_to(const equalizable &s2) const {
62 const byte_array *s2_cast = dynamic_cast<const byte_array *>(&s2);
63 if (!s2_cast) throw "error: byte_array::==: unknown type";
64 return comparator(*s2_cast) == 0;
66 virtual bool less_than(const orderable &s2) const {
67 const byte_array *s2_cast = dynamic_cast<const byte_array *>(&s2);
68 if (!s2_cast) throw "error: byte_array::<: unknown type";
69 return comparator(*s2_cast) < 0;
72 int comparator(const byte_array &s2) const {
73 return memcmp(observe(), s2.observe(), length());
79 //! A base class for objects that can pack into an array of bytes.
81 A packable is an abstract object that represents any object that can
82 be transformed from a potentially deep form into an equivalent flat
83 form. The flat form is a simple extent of memory stored as bytes.
86 class packable : public virtual root_object
89 virtual void pack(byte_array &packed_form) const = 0;
90 //!< Creates a packed form of the packable object in "packed_form".
91 /*!< This must append to the data in "packed_form" rather than clearing
94 virtual bool unpack(byte_array &packed_form) = 0;
95 //!< Restores the packable from the "packed_form".
96 /*!< This object becomes the unpacked form, and therefore must lose any of
97 its prior contents that depend on the data in "packed_form". This is up to
98 the derived unpack function to figure out. The "packed_form" is modified
99 by extracting all of the pieces that are used for this object; the
100 remainder stays in "packed_form". true is returned if the unpacking was
103 virtual int packed_size() const = 0;
104 //!< Estimates the space needed for the packed structure.
109 // the two templates below can be used to add or remove objects from an array
110 // of bytes. NOTE: the functions below will only work with objects that are
111 // already platform-independent. it's better to make structures packable by
112 // using the attach and detach functions in the "packable" library.
114 //! attach_flat() places a copy of "attachment" onto the array of bytes.
115 template <class contents>
116 void attach_flat(byte_array &target, const contents &attachment)
117 { target.concatenate(byte_array(sizeof(attachment), (abyte *)&attachment)); }
119 //! detach_flat() pulls the "detached" object out of the array of bytes.
120 template <class contents>
121 bool detach_flat(byte_array &source, contents &detached)
123 if (sizeof(detached) > source.length()) return false;
124 detached = *(contents *)source.observe();
125 source.zap(0, sizeof(detached) - 1);