00001 #include "bstr.h"
00002
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <stdio.h>
00006
00007 cp_bstr *cp_bstr_create(int length, unsigned char *bits)
00008 {
00009 int bytecount;
00010 cp_bstr *seq = (cp_bstr *) malloc(sizeof(cp_bstr));
00011 if (seq == NULL) return NULL;
00012
00013 bytecount = (length + 7) >> 3;
00014 seq->bits = (unsigned char *) malloc(bytecount);
00015 if (seq->bits == NULL)
00016 {
00017 free(seq);
00018 return NULL;
00019 }
00020
00021 if (bits != NULL)
00022 memcpy(seq->bits, bits, bytecount);
00023
00024 seq->length = length;
00025
00026 return seq;
00027 }
00028
00029
00030
00031
00032
00033 cp_bstr *cstr_to_bstr(char *str)
00034 {
00035 int i, pos, len, bytecount, bit;
00036 cp_bstr *seq;
00037
00038 seq = (cp_bstr *) malloc(sizeof(cp_bstr));
00039 if (seq == NULL) return NULL;
00040
00041 len = strlen(str);
00042 bytecount = (len + 7) / 8;
00043
00044 seq->bits = (unsigned char *) calloc(1, bytecount);
00045 if (seq->bits == NULL)
00046 {
00047 free(seq);
00048 return NULL;
00049 }
00050
00051 seq->length = len;
00052 for (i = 0, pos = 0, bit = 0x80; i < len; i++)
00053 {
00054 if (str[i] == '1')
00055 seq->bits[pos] |= bit;
00056 bit >>= 1;
00057 if (bit == 0)
00058 {
00059 bit = 0x80;
00060 pos++;
00061 }
00062 }
00063
00064 return seq;
00065 }
00066
00067 void cp_bstr_destroy(cp_bstr *seq)
00068 {
00069 if (seq)
00070 {
00071 free(seq->bits);
00072 free(seq);
00073 }
00074 }
00075
00076 void cp_bstr_dump(cp_bstr *seq)
00077 {
00078 int i, pos;
00079
00080 printf("bit sequence: %d bits\n", seq->length);
00081
00082 for (i = 0, pos = 0; i < seq->length; i++)
00083 {
00084 if (seq->bits[pos] & (0x80 >> (i % 8)))
00085 printf("1");
00086 else
00087 printf("0");
00088
00089 if (((i + 1) % 8) == 0) pos++;
00090 }
00091
00092 printf("\n");
00093 }
00094
00095 char *cp_bstr_to_string(cp_bstr *seq)
00096 {
00097 int i, pos;
00098 char *res = (char *) malloc(seq->length + 1);
00099 if (res == NULL) return NULL;
00100
00101 for (i = 0, pos = 0; i < seq->length; i++)
00102 {
00103 if (seq->bits[pos] & (0x80 >> (i % 8)))
00104 res[i] = '1';
00105 else
00106 res[i] = '0';
00107
00108 if (((i + 1) % 8) == 0) pos++;
00109 }
00110
00111 res[i] = '\0';
00112
00113 return res;
00114 }
00115
00116 cp_bstr *cp_bstr_dup(cp_bstr *seq)
00117 {
00118 int bytecount;
00119 cp_bstr *dup;
00120
00121 dup = (cp_bstr *) malloc(sizeof(cp_bstr));
00122 if (dup == NULL) return NULL;
00123
00124 bytecount = BYTECOUNT(seq);
00125 dup->bits = (unsigned char *) malloc(bytecount);
00126 if (dup->bits == NULL)
00127 {
00128 free(dup);
00129 return NULL;
00130 }
00131
00132 memcpy(dup->bits, seq->bits, bytecount);
00133 dup->length = seq->length;
00134
00135 return dup;
00136 }
00137
00138 cp_bstr *cp_bstr_cpy(cp_bstr *dst, cp_bstr *src)
00139 {
00140 int bytecount_src, bytecount_dst;
00141
00142 bytecount_src = BYTECOUNT(src);
00143 bytecount_dst = BYTECOUNT(dst);
00144
00145 if (bytecount_src > bytecount_dst)
00146 {
00147 if (dst->length > 0)
00148 free(dst->bits);
00149
00150 dst->bits = (unsigned char *) malloc(bytecount_src);
00151 if (dst->bits == NULL) return NULL;
00152 }
00153
00154 memcpy(dst->bits, src->bits, bytecount_dst);
00155 src->length = dst->length;
00156
00157 return dst;
00158 }
00159
00160 static unsigned char bstr_mask[] =
00161 {
00162 0x80,
00163 0xC0,
00164 0xE0,
00165 0xF0,
00166 0xF8,
00167 0xFC,
00168 0xFE,
00169 0xFF
00170 };
00171
00172 cp_bstr *cp_bstr_cat(cp_bstr *head, cp_bstr *tail)
00173 {
00174 int old_bytecount = BYTECOUNT(head);
00175 int pos = head->length;
00176 int cpos = old_bytecount << 3;
00177 int diff = cpos - pos;
00178 int newlen = head->length + tail->length;
00179 int new_bytecount = (newlen + 7) >> 3;
00180
00181 int in_place = head == tail;
00182 if (in_place)
00183 tail = cp_bstr_dup(tail);
00184
00185 if (new_bytecount > old_bytecount)
00186 {
00187 unsigned char *p = (unsigned char *) malloc(new_bytecount);
00188 if (p == NULL) return NULL;
00189
00190 memcpy(p, head->bits, old_bytecount);
00191 free(head->bits);
00192 head->bits = p;
00193 }
00194
00195 if (diff == 0)
00196 {
00197 memcpy(&head->bits[old_bytecount], tail->bits, BYTECOUNT(tail));
00198 }
00199 else
00200 {
00201 int i;
00202
00203
00204
00205
00206
00207
00208 int stretch = new_bytecount - old_bytecount;
00209 head->bits[old_bytecount - 1] &= bstr_mask[(head->length % 8) - 1];
00210 for (i = 0; i < stretch; i++)
00211 {
00212 head->bits[old_bytecount - 1 + i] |= tail->bits[i] >> (8 - diff);
00213 head->bits[old_bytecount + i] = tail->bits[i] << diff;
00214 }
00215 if (stretch < BYTECOUNT(tail))
00216 head->bits[old_bytecount + stretch - 1] |= tail->bits[stretch] >> (8 - diff);
00217 }
00218
00219 head->length = newlen;
00220
00221 if (in_place)
00222 cp_bstr_destroy(tail);
00223
00224 return head;
00225 }
00226
00227 int cp_bstr_cmp(cp_bstr *a, cp_bstr *b, int *rpos)
00228 {
00229 int pos;
00230 int ca, cb, len;
00231 int atail, btail;
00232 int acmp, bcmp, shift;
00233 unsigned long long *llpa;
00234 unsigned long long *llpb;
00235 int llen;
00236
00237 ca = BYTECOUNT(a);
00238 atail = ca * 8 - a->length;
00239 if (atail > 0) ca--;
00240
00241 cb = BYTECOUNT(b);
00242 btail = cb * 8 - b->length;
00243 if (btail > 0) cb--;
00244
00245 len = ca < cb ? ca : cb;
00246
00247 pos = 0;
00248
00249 if (len > sizeof(long long))
00250 {
00251 llpa = a->bits;
00252 llpb = b->bits;
00253 llen = len / 8;
00254
00255 for ( ; pos < llen; pos++)
00256 {
00257 if (*llpa != *llpb)
00258 break;
00259 llpa++;
00260 llpb++;
00261 }
00262 if (pos != llen)
00263 {
00264 pos *= sizeof(long long);
00265 pos += CP_CLZ_LONG_LONG(*llpa ^ *llpb);
00266 goto FOUND;
00267 }
00268 pos *= sizeof(long long);
00269 }
00270
00271 for ( ; pos < len; pos++)
00272 if (a->bits[pos] != b->bits[pos])
00273 break;
00274 FOUND:
00275 if (pos < len)
00276 {
00277 if (rpos != NULL)
00278 *rpos = pos * 8 + CP_CLZ_CHAR(a->bits[pos] ^ b->bits[pos]);
00279
00280 return a->bits[pos] - b->bits[pos];
00281 }
00282
00283 acmp = bcmp = -1;
00284 shift = 0;
00285
00286 if (len < ca)
00287 acmp = a->bits[len];
00288 else if (atail > 0)
00289 {
00290 acmp = a->bits[len] & bstr_mask[7 - atail];
00291 shift = atail;
00292 }
00293
00294 if (len < cb)
00295 bcmp = b->bits[len];
00296 else if (btail > 0)
00297 {
00298 bcmp = b->bits[len] & bstr_mask[7 - btail];
00299 #define BMAX(a, b) ((a) > (b) ? (a) : (b))
00300 shift = BMAX(shift, btail);
00301 }
00302
00303 if (acmp != -1 && bcmp != -1)
00304 {
00305 if (shift)
00306 {
00307 acmp >>= shift;
00308 bcmp >>= shift;
00309 }
00310
00311 if (acmp == bcmp)
00312 {
00313 len = a->length - b->length;
00314 if (rpos != NULL)
00315 *rpos = len < 0 ? a->length : b->length;
00316 return len;
00317 }
00318 else
00319 {
00320 if (rpos != NULL)
00321 *rpos = (pos * 8 + CP_CLZ_CHAR(acmp ^ bcmp)) - shift;
00322 return (acmp - bcmp) << shift;
00323 }
00324 }
00325
00326 if (rpos != NULL)
00327 *rpos = pos * 8;
00328
00329 return 0;
00330 }
00331
00332
00333
00334
00335 int cp_bstr_shift_left(cp_bstr *seq, int count)
00336 {
00337 int i;
00338 int bytes = count / 8;
00339 int bits = count - bytes * 8;
00340 int len = BYTECOUNT(seq) - bytes;
00341
00342 if (len > 0)
00343 memmove(seq->bits, &seq->bits[bytes], len);
00344
00345 if (bits > 0)
00346 {
00347 seq->bits[0] <<= bits;
00348 for (i = 1; i < len; i++)
00349 {
00350 seq->bits[i - 1] |= seq->bits[i] >> (8 - bits);
00351 seq->bits[i] <<= bits;
00352 }
00353 }
00354
00355 seq->length -= count;
00356
00357 return seq->length;
00358 }
00359