00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "bytes_seq.H"
00031
00032 typedef char *chars;
00033 typedef bytes_seq_impl::rep rep;
00034
00035
00036
00037
00038
00039 inline int round_up(int v, int m) { return ((v + m - 1)/m)*m; }
00040
00041 rep *bytes_seq_impl::allocate_buffer(int len_hint, int bytes)
00042 {
00043
00044
00045
00046 int size = bytes_seq::min_size(len_hint) + round_up(bytes, sizeof(chars));
00047 char* buffer = (char*) NEW_PTRFREE_ARRAY(chars, size/sizeof(chars));
00048 rep *p = (rep *) buffer;
00049 p->h.storage = grow;
00050 p->h.len = 0;
00051 p->h.bodies = p->h.limit = &buffer[size];
00052 return p;
00053 }
00054
00055 void bytes_seq_impl::expand(bytes_seq_impl::rep *&p,
00056 int len_hint,
00057 int min_body_add)
00058 {
00059 if (p->h.storage == manual)
00060 throw(bytes_seq::failure("Buffer has insufficient space."));
00061
00062
00063
00064
00065 int new_len = len_hint < 0 ? p->h.len : len_hint;
00066 int body_space =
00067 min_body_add >= 0 ? max(2*(p->h.limit - p->h.bodies), min_body_add) : 0;
00068 rep *new_p = allocate_buffer(new_len, body_space);
00069
00070 new_p->h.storage = p->h.storage;
00071 new_p->h.bodies = new_p->h.limit - body_space;
00072
00073
00074 memcpy(new_p->h.bodies, p->h.bodies, body_space);
00075
00076
00077
00078
00079 byte_str *seq = &p->base;
00080 byte_str *new_seq = &new_p->base;
00081 int offset = new_p->h.bodies - p->h.bodies;
00082 for (int i = 0; i < p->h.len; i++) {
00083 assert(seq[i].p >= p->h.bodies && seq[i].p < p->h.limit);
00084 new_seq[i].p = seq[i].p + offset;
00085 new_seq[i].l = seq[i].l;
00086 }
00087 new_p->h.len = p->h.len;
00088
00089 delete[] (chars *)p;
00090 p = new_p;
00091
00092 }
00093
00094
00095
00096
00097
00098
00099 bytes_seq::bytes_seq(int len_hint, int bytes)
00100 {
00101 if (len_hint == 0 && bytes == 0)
00102
00103
00104
00105 p = NULL;
00106 else p = bytes_seq_impl::allocate_buffer(len_hint, bytes);
00107 }
00108
00109 bytes_seq::bytes_seq(void **buffer, int bytes) throw (bytes_seq::failure)
00110 {
00111 p = (rep *)buffer;
00112 p->h.storage = bytes_seq_impl::manual;
00113 p->h.len = 0;
00114 p->h.bodies = p->h.limit = (char *)buffer + bytes;
00115 }
00116
00117 bytes_seq::~bytes_seq()
00118 {
00119 if (p == NULL || p->h.storage == bytes_seq_impl::manual) return;
00120 delete[] (chars *)p;
00121 }
00122
00123 int bytes_seq::min_size(int len)
00124 {
00125
00126
00127
00128
00129
00130 return
00131 round_up(sizeof(bytes_seq_impl::rep) + (len-1)*(sizeof(byte_str)),
00132 sizeof(chars));
00133 }
00134
00135
00136
00137
00138
00139
00140 void bytes_seq::append(const byte_str &b) throw(bytes_seq::failure)
00141 {
00142 if (p == NULL) p = bytes_seq_impl::allocate_buffer();
00143 int bytes_for_body = b.l;
00144 byte_str *seq = &p->base;
00145 char *s_copy = p->h.bodies - bytes_for_body;
00146
00147
00148
00149 if (&seq[p->h.len+1].p > (chars *)s_copy) {
00150
00151 bytes_seq_impl::expand(p, 1+2*p->h.len, bytes_for_body);
00152
00153 seq = &p->base;
00154 s_copy = p->h.bodies - bytes_for_body;
00155 }
00156
00157 assert(&seq[p->h.len+1].p <= (chars *)s_copy);
00158
00159 strcpy(s_copy, b.p);
00160 seq[p->h.len].p = p->h.bodies = s_copy;
00161 seq[p->h.len].l = bytes_for_body;
00162 p->h.len++;
00163 }