Merge branch 'release-2.140.101'
[feisty_meow.git] / nucleus / library / basis / byte_array.h
1 #ifndef BYTE_ARRAY_CLASS
2 #define BYTE_ARRAY_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : byte_array                                                        *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
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 \*****************************************************************************/
17
18 #include "array.h"
19 #include "base_string.h"
20 #include "contracts.h"
21 #include "definitions.h"
22
23 #include <string.h>  // for memcmp.
24
25 namespace basis {
26
27 //! A very common template for a dynamic array of bytes.
28 /*!
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.
33 */
34
35 class byte_array : public array<abyte>, public virtual orderable
36 {
37 public:
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".
41
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.
45
46   byte_array(const array<abyte> &to_copy) : array<abyte>(to_copy) {}
47     //!< constructs an array bytes by copying the "to_copy" array.
48
49   virtual ~byte_array() {}
50
51   DEFINE_CLASS_NAME("byte_array");
52
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
56   library. */
57   static const byte_array &empty_array()
58       { static byte_array g_empty; return g_empty; }
59
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;
65   }
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;
70   }
71
72   int comparator(const byte_array &s2) const { 
73     return memcmp(observe(), s2.observe(), length());
74   }
75 };
76
77 //////////////
78
79 //! A base class for objects that can pack into an array of bytes.
80 /*!
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.
84 */
85
86 class packable : public virtual root_object
87 {
88 public:
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
92     prior contents. */
93
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
101     successful. */
102
103   virtual int packed_size() const = 0;
104     //!< Estimates the space needed for the packed structure.
105 };
106
107 //////////////
108
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.
113
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)); }
118
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)
122 {
123   if (sizeof(detached) > source.length()) return false;
124   detached = *(contents *)source.observe();
125   source.zap(0, sizeof(detached) - 1);
126   return true;
127 }
128
129 } // namespace.
130
131 #endif
132