/*#io
docCopyright("Steve Dekorte", 2002)
docLicense("BSD revised")
*/
#include "Base.h"
#define BYTEARRAY_C
#include "ByteArray.h"
#undef BYTEARRAY_C
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
ByteArray *ByteArray_new(void)
{
return ByteArray_newWithSize_(0);
}
ByteArray *ByteArray_newWithCString_(const char *s)
{
return ByteArray_newWithData_size_((const unsigned char *)s, strlen(s));
}
ByteArray *ByteArray_newWithCString_size_(const char *s, int size)
{
return ByteArray_newWithData_size_((const unsigned char *)s, size);
}
ByteArray *ByteArray_newWithSize_(int size)
{
ByteArray *self = (ByteArray *)calloc(1, sizeof(ByteArray));
self->bytes = (unsigned char *)calloc(1, size + 1);
self->size = size;
self->memSize = size;
return self;
}
ByteArray *ByteArray_newWithData_size_(const unsigned char* buf, size_t size)
{
ByteArray *self = (ByteArray *)calloc(1, sizeof(ByteArray));
self->bytes = (unsigned char *)malloc(size + 1);
self->bytes[size] = (unsigned char)0;
memcpy(self->bytes, buf, size);
self->size = size;
return self;
}
ByteArray *ByteArray_clone(ByteArray *self)
{
return ByteArray_newWithData_size_(self->bytes, self->size);
}
// datum ------------------------------------------------
Datum ByteArray_asDatum(ByteArray *self)
{
Datum d;
d.data = self->bytes;
d.size = self->size;
return d;
}
Datum *ByteArray_asNewDatum(ByteArray *self)
{
Datum *d = (Datum *)malloc(sizeof(Datum));
d->data = self->bytes;
d->size = self->size;
return d;
}
Datum ByteArray_datumAt_(ByteArray *self, size_t i)
{
Datum d = ByteArray_asDatum(self);
return Datum_datumAt_(&d, i);
}
// ----------------------------------------------------------
void ByteArray_free(ByteArray *self)
{
/*
if (self == (void *)0x5c5c990)
{
printf("ByteArray_free(%p)\n", self);
}
*/
if (self->bytes)
{
free(self->bytes);
}
free(self);
}
size_t ByteArray_memorySize(ByteArray *self)
{
return sizeof(ByteArray) + self->memSize;
}
void ByteArray_compact(ByteArray *self)
{
size_t newSize = self->size + 1;
if (self->memSize > newSize)
{
unsigned char *b = (unsigned char *)malloc(newSize);
memcpy(b, self->bytes, newSize);
free(self->bytes);
self->memSize = newSize;
self->bytes = b;
}
}
void ByteArray_clear(ByteArray *self)
{
memset(self->bytes, 0, self->size);
self->size = 0;
}
void ByteArray_setAllBytesTo_(ByteArray *self, unsigned char c)
{
memset(self->bytes, (int)c, self->size);
}
void ByteArray_sizeTo_(ByteArray *self, size_t size)
{
if (size > self->memSize)
{
//if (self->memSize == 0) self->bytes = 0;
self->bytes = (unsigned char *)realloc(self->bytes, size + 1);
self->memSize = size;
}
self->bytes[size] = (unsigned char)0;
if (self->size > size)
{
self->size = size;
}
}
void ByteArray_setSize_(ByteArray *self, size_t size)
{
ByteArray_sizeTo_(self, size);
self->size = size;
}
void ByteArray_copy_(ByteArray *self, ByteArray *other)
{
ByteArray_setData_size_(self, other->bytes, other->size);
//printf("self %p size %i memSize %i\n", (void *)self, (int)self->size, (int)self->memSize);
//printf("other %p size %i memSize %i\n", (void *)other, (int)other->size, (int)other->memSize);
}
void ByteArray_setData_size_(ByteArray *self, const unsigned char *bytes, size_t size)
{
ByteArray_setSize_(self, size);
if (size)
{
memcpy(self->bytes, bytes, size);
}
}
void ByteArray_setCString_(ByteArray *self, const char *s)
{
ByteArray_setData_size_(self, (unsigned char *)s, (size_t)strlen(s));
}
// single byte/character operations ------------------------
int ByteArray_hasDigit(ByteArray *self)
{
size_t i;
for (i = 0; i < self->size; i ++)
{
if (isdigit(self->bytes[i]))
{
return 1;
}
}
return 0;
}
unsigned long ByteArray_at_bytesCount_(ByteArray *self, int i, int l)
{
int n;
long d = 0;
if (!((i >= 0) && ((size_t)(i + l) <= ByteArray_size(self))))
{
return 0;
}
// pack bytes into a Number
for (n = i + l - 1; n >= i; n --)
{
d = d << 8;
d = d | (self->bytes[n]);
}
return d;
}
int ByteArray_at_put_(ByteArray *self, int pos, unsigned char c)
{
int len = self->size;
if (pos < - len)
{
return 0;
}
if (pos > len)
{
ByteArray_setSize_(self, pos);
}
pos = ByteArray_wrapPos_(self, pos);
if (len == -1 || pos > len - 1)
{
return 0;
}
self->bytes[ByteArray_wrapPos_(self, pos)] = c;
return 1;
}
unsigned char ByteArray_dropLastByte(ByteArray *self)
{
unsigned char c = 0;
if (self->size)
{
self->size --;
c = self->bytes[self->size];
self->bytes[self->size] = 0;
}
return c;
}
void ByteArray_removeByteAt_(ByteArray *self, int pos)
{
ByteArray_removeSlice(self, pos, pos + 1);
}
void ByteArray_removeCharAt_(ByteArray *self, int pos)
{
int csize = BYTEARRAY_BYTES_PER_CHARACTER;
int len = self->size;
if (len < 1)
{
return;
}
pos = ByteArray_wrapPos_(self, pos);
memmove(self->bytes + pos * csize,
self->bytes + (pos + 1) * csize,
(len - pos + 1) * csize);
}
void ByteArray_removeSlice(ByteArray *self, int from, int to)
{
int len = self->size;
if (len < 1)
{
return;
}
from = ByteArray_wrapPos_(self, from);
to = ByteArray_wrapPos_(self, to);
memmove(self->bytes + from, self->bytes + to, len - to);
ByteArray_setSize_(self, len - (to - from));
}
// escape --------------------------------------------
void ByteArray_escape(ByteArray *self)
{
ByteArray *ba = ByteArray_new();
char *s = (char *)self->bytes;
size_t i;
for (i = 0; i < self->size; i ++)
{
char c = s[i];
switch (c)
{
case '"': ByteArray_appendCString_(ba, "\\\""); break;
case '\a': ByteArray_appendCString_(ba, "\\a"); break;
case '\b': ByteArray_appendCString_(ba, "\\b"); break;
case '\f': ByteArray_appendCString_(ba, "\\f"); break;
case '\n': ByteArray_appendCString_(ba, "\\n"); break;
case '\r': ByteArray_appendCString_(ba, "\\r"); break;
case '\t': ByteArray_appendCString_(ba, "\\t"); break;
case '\v': ByteArray_appendCString_(ba, "\\v"); break;
case '\\': ByteArray_appendCString_(ba, "\\\\"); break;
default: ByteArray_appendChar_(ba, c);
}
}
s[i] = (char)NULL;
ByteArray_copy_(self, ba);
ByteArray_free(ba);
}
void ByteArray_unescape(ByteArray *self)
{
int mbskip = 0; /* multi-byte character size */
size_t getIndex = 0;
size_t putIndex = 0;
char *s = (char *)self->bytes;
while (getIndex < self->size)
{
int c = s[getIndex];
int nextChar = s[getIndex + 1];
if (mbskip <= 0 && ismbchar(c))
{
mbskip = mbcharlen(c);
}
if (c != '\\' || mbskip > 0)
{
mbskip --;
if (getIndex != putIndex)
{
s[putIndex] = c;
}
putIndex ++;
}
else
{
char c = nextChar;
switch (c)
{
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
case '\0': c = '\\'; break;
default:
if (isdigit(c))
{
c -= 48;
}
}
s[putIndex] = c;
getIndex ++;
putIndex ++;
}
getIndex++;
}
s[putIndex] = (char)NULL;
ByteArray_setSize_(self, putIndex);
}
void ByteArray_quote(ByteArray *self)
{
int oldSize = self->size;
ByteArray_setSize_(self, self->size + 2);
memmove(self->bytes + 1, self->bytes, oldSize);
self->bytes[0] = '"';
self->bytes[self->size - 1] = '"';
}
void ByteArray_unquote(ByteArray *self)
{
if (self->size == 2)
{
ByteArray_setSize_(self, 0);
}
else
{
memmove(self->bytes, self->bytes + 1, self->size - 1);
ByteArray_setSize_(self, self->size - 2);
}
}
// append --------------------------------------------
void ByteArray_appendChar_(ByteArray *self, char c)
{
ByteArray_appendBytes_size_(self, (const unsigned char *)(&c), 1);
}
void ByteArray_appendByte_(ByteArray *self, unsigned char c)
{
ByteArray_appendBytes_size_(self, &c, 1);
}
void ByteArray_append_(ByteArray *self, ByteArray *other)
{
// Don't use, ByteArray_appendBytes_size_(self, other->bytes, other->size);
// because it can copy the wrong memory when self == other and a resize occurs.
int otherSize = other->size;
if(otherSize)
{
int selfSize = self->size;
ByteArray_setSize_(self, selfSize + otherSize);
memcpy(self->bytes + selfSize, other->bytes, otherSize);
}
}
void ByteArray_appendCString_(ByteArray *self, const char *s)
{
ByteArray_appendBytes_size_(self, (const unsigned char *)s, strlen(s));
}
void ByteArray_appendAndEscapeCString_(ByteArray *self, const char *s)
{
char oneChar[2];
oneChar[1] = (char)0;
while (*s)
{
if (*s == '\n')
{
ByteArray_appendBytes_size_(self, (const unsigned char *)"\\n", 2);
}
else if (*s == '\t')
{
ByteArray_appendBytes_size_(self, (const unsigned char *)"\\t", 2);
}
else if (*s == '"')
{
ByteArray_appendBytes_size_(self, (const unsigned char *)"\\\"", 2);
}
else
{
oneChar[0] = *s;
ByteArray_appendBytes_size_(self, (const unsigned char *)oneChar, 1);
}
s ++;
}
self->bytes[self->size] = (unsigned char)0;
}
void ByteArray_appendBytes_size_(ByteArray *self, const unsigned char *bytes, size_t size)
{
int oldSize;
if(size == 0)
return;
oldSize = self->size;
ByteArray_setSize_(self, oldSize + size);
memcpy(self->bytes + oldSize, bytes, size);
//self->bytes[self->size] = (unsigned char)0; // not needed?
}
// prepend --------------------------------------------
void ByteArray_prepend_(ByteArray *self, ByteArray *other)
{
ByteArray_prependBytes_size_(self, other->bytes, other->size);
}
void ByteArray_prependCString_(ByteArray *self, const char *s)
{
ByteArray_prependBytes_size_(self, (const unsigned char *)s, strlen(s));
}
void ByteArray_prependBytes_size_(ByteArray *self, const unsigned char *bytes, size_t size)
{
int oldSize = self->size;
ByteArray_setSize_(self, oldSize + size);
memmove(self->bytes + size, self->bytes, oldSize);
memcpy(self->bytes, bytes, size);
}
// subarray --------------------------------------------
ByteArray *ByteArray_newWithBytesFrom_to_(ByteArray *self, int startpos, int endpos)
{
int newlen;
startpos = ByteArray_wrapPos_(self, startpos);
endpos = ByteArray_wrapPos_(self, endpos);
newlen = endpos - startpos;
if (newlen < 1)
{
return ByteArray_new();
}
return ByteArray_newWithData_size_(self->bytes+startpos, newlen);
}
// insert --------------------------------------------
void ByteArray_insert_at_(ByteArray *self, ByteArray *other, size_t pos)
{
ByteArray_insertBytes_size_at_(self, other->bytes, other->size, pos);
}
void ByteArray_insertCString_at_(ByteArray *self, const char *s, size_t pos)
{
ByteArray_insertBytes_size_at_(self, (const unsigned char *)s, strlen(s), pos);
}
void ByteArray_insertBytes_size_at_(ByteArray *self, const unsigned char *bytes, size_t size, size_t pos)
{
long oldSize = self->size;
pos = ByteArray_wrapPos_(self, pos);
if (pos == self->size)
{
ByteArray_appendBytes_size_(self, bytes, size);
return;
}
ByteArray_setSize_(self, self->size + size);
memmove(self->bytes + pos + size, self->bytes + pos, oldSize - pos);
memcpy(self->bytes + pos, bytes, size);
}
// clipping --------------------------------------------
char ByteArray_clipBefore_(ByteArray *self, ByteArray *other)
{
int i = ByteArray_find_(self, other);
if (i == -1) return 0;
ByteArray_removeSlice(self, 0, i);
return 1;
}
char ByteArray_clipBeforeEndOf_(ByteArray *self, ByteArray *other)
{
int i = ByteArray_find_(self, other);
if (i == -1) return 0;
ByteArray_removeSlice(self, 0, i + ByteArray_size(other));
return 1;
}
char ByteArray_clipAfter_(ByteArray *self, ByteArray *other)
{
int i = ByteArray_find_(self, other);
if (i == -1) return 0;
ByteArray_removeSlice(self, i + ByteArray_size(other), ByteArray_size(self));
return 1;
}
char ByteArray_clipAfterStartOf_(ByteArray *self, ByteArray *other)
{
int i = ByteArray_find_(self, other);
if (i == -1) return 0;
ByteArray_removeSlice(self, i, ByteArray_size(self));
return 1;
}
// strip --------------------------------------------
int ByteArray_containsByte_(ByteArray *self, unsigned char b)
{
size_t i;
for (i = 0; i < self->size; i ++)
{
unsigned char c = self->bytes[i];
if (c == b)
{
return 1;
}
}
return 0;
}
void ByteArray_strip_(ByteArray *self, ByteArray *other)
{
ByteArray_lstrip_(self, other);
ByteArray_rstrip_(self, other);
}
void ByteArray_lstrip_(ByteArray *self, ByteArray *other)
{
size_t i;
for (i = 0; i < self->size; i ++)
{
unsigned char c = self->bytes[i];
if (!ByteArray_containsByte_(other, c))
{
break;
}
}
ByteArray_removeSlice(self, 0, i);
}
void ByteArray_rstrip_(ByteArray *self, ByteArray *other)
{
size_t i = self->size;
do
{
i --;
if (!ByteArray_containsByte_(other, self->bytes[i]))
{
break;
}
} while (i != 0);
ByteArray_removeSlice(self, i + 1, self->size);
}
// enumerating --------------------------------------------
typedef int (ByteArrayDetectFunc)(int);
int ByteArray_detect_(ByteArray *self, ByteArrayDetectFunc *func)
{
unsigned char *s = self->bytes;
unsigned char *end = self->bytes + self->size;
while (s < end)
{
if ((*func)(*s))
{
return s - self->bytes;
}
s ++;
}
return -1;
}
typedef int (ByteArrayDetectWithFunc)(void *, Datum *);
int ByteArray_detect_with_(ByteArray *self, ByteArrayDetectWithFunc *func, void *arg)
{
unsigned char *s = self->bytes;
unsigned char *end = self->bytes + self->size;
Datum d;
while (s < end)
{
d.data = s;
d.size = end - s;
if ((*func)(arg, &d))
{
return s - self->bytes;
}
s ++;
}
return -1;
}
//typedef unsigned char (ByteArrayCollectFunc)(unsigned char);
// tolower and toupper use this signature:
typedef int (ByteArrayCollectFunc)(int);
void ByteArray_collectInPlace_(ByteArray *self, ByteArrayCollectFunc *func)
{
unsigned char *s = self->bytes;
unsigned char *end = self->bytes + self->size;
while (s < end)
{
*s = (*func)(*s);
s ++;
}
}
// case --------------------------------------------
int ByteArray_isLowercase(ByteArray *self)
{
return ByteArray_detect_(self, (ByteArrayDetectFunc *)isupper) == -1;
}
int ByteArray_isUppercase(ByteArray *self)
{
return ByteArray_detect_(self, (ByteArrayDetectFunc *)islower) == -1;
}
void ByteArray_Lowercase(ByteArray *self)
{
ByteArray_collectInPlace_(self, (ByteArrayCollectFunc *)tolower);
}
void ByteArray_uppercase(ByteArray *self)
{
ByteArray_collectInPlace_(self, (ByteArrayCollectFunc *)toupper);
}
// string comparision operations --------------------------------
int ByteArray_equals_(ByteArray *self, ByteArray *other)
{
// returns 1 if equal, 0 if not equal.
if (self->size != other->size)
{
return 0;
}
return (memcmp(self->bytes, other->bytes, self->size) == 0);
}
int ByteArray_equalsAnyCase_(ByteArray *self, ByteArray *other)
{
if (self->size == other->size)
{
if (self->size == 0) return 1;
return ByteArray_containsAnyCase_(self, other);
}
return 0;
}
int ByteArray_contains_(ByteArray *self, ByteArray *other)
{
return (ByteArray_find_(self, other) != -1);
}
int ByteArray_containsAnyCase_(ByteArray *self, ByteArray *other)
{
return (ByteArray_findAnyCase_(self, other) != -1);
}
int ByteArray_find_(ByteArray *self, ByteArray *other)
{
return ByteArray_find_from_(self, other, 0);
}
int ByteArray_beginsWith_(ByteArray *self, ByteArray *other)
{
if (!other->size)
{
return 1;
}
if (!self->size || other->size > self->size)
{
return 0;
}
return (memcmp((char *)(self->bytes), (char *)(other->bytes), other->size) == 0);
}
int ByteArray_endsWith_(ByteArray *self, ByteArray *other)
{
int sl = self->size;
int ol = other->size;
if (!ol)
{
return 1;
}
if (!sl || ol > sl)
{
return 0;
}
return (memcmp((char *)(self->bytes + sl - ol), (char *)other->bytes, ol) == 0);
}
int ByteArray_findAnyCase_(ByteArray *self, ByteArray *other)
{
return ByteArray_findAnyCase_from_(self, other, 0);
}
static int ByteArray_contains_at_(ByteArray *self, ByteArray *other, size_t from)
{
if (from >= self->size || self->size - from < other->size)
{
return 0;
}
return (memcmp(self->bytes + from, other->bytes, other->size) == 0);
}
// return -1 for no match, starting position of match if found
int ByteArray_find_from_(ByteArray *self, ByteArray *other, int from)
{
int i, max = self->size - other->size + 1;
from = ByteArray_wrapPos_(self, from);
//string_caseInsensitiveBoyerMooreSearch()
for (i = from; i < max; i ++)
{
if (ByteArray_contains_at_(self, other, i))
{
return i;
}
}
return -1;
}
int ByteArray_findCString_from_(ByteArray *self, const char *other, int from)
{
from = ByteArray_wrapPos_(self, from);
{
char *p = strstr((char *)(self->bytes + from), other);
ptrdiff_t rval;
if (!p)
{
return -1;
}
rval = (ptrdiff_t)p - (ptrdiff_t)(self->bytes);
return rval;
}
}
int ByteArray_rFindCString_from_(ByteArray *self, const char *other, int from)
{
// return -1 for no match, starting position of match if found
unsigned char *bytes = self->bytes;
size_t otherLen = strlen(other);
from = ByteArray_wrapPos_(self, from);
bytes = bytes + from - otherLen;
while (bytes >= self->bytes)
{
if (memcmp(bytes, other, otherLen) == 0)
{
return bytes - self->bytes;
}
bytes --;
}
return -1;
}
int ByteArray_rFind_from_(ByteArray *self, ByteArray *other, int from)
{
// return -1 for no match, starting position of match if found
unsigned char *bytes = self->bytes;
from = ByteArray_wrapPos_(self, from);
bytes = bytes + from - other->size;
while (bytes >= self->bytes)
{
if (memcmp(bytes, other->bytes, other->size) == 0)
{
return bytes - self->bytes;
}
bytes --;
}
return -1;
}
int ByteArray_rFindCharacters_from_(ByteArray *self, const char *chars, int from)
{
// return -1 for no match, starting position of match if found
unsigned char *start = self->bytes;
unsigned char *p = self->bytes;
const char* pChar = NULL;
from = ByteArray_wrapPos_(self, from);
p = p + from - 1; // -1 : the from index is not included in the search
// for each byte in self
while( start <= p )
{
// for each character to match
for( pChar = chars; *pChar ; ++pChar )
{
if( *pChar == *p )
{
return p - start;
}
}
--p;
}
return -1;
}
int ByteArray_findAnyCase_from_(ByteArray *self, ByteArray *other, int from)
{
// return -1 for no match
size_t n, m;
size_t len2 = other->size;
size_t max = self->size - other->size;
from = ByteArray_wrapPos_(self, from);
if (self->size < len2) return -1; // too big
if (len2 <= 0) return -1; // too small
for (n = from; n <= max; n++)
{
m = 0;
while ((tolower(self->bytes[n+m]) == tolower(other->bytes[m]) && (m < len2 + 1)))
{
if (m == len2 - 1)
{
return n;
}
m ++;
}
}
return -1;
}
int ByteArray_findByteWithValue_from_(ByteArray *self, unsigned char v, int from)
{
unsigned char *b = self->bytes;
size_t index = from;
size_t max = self->size;
while (index < max)
{
if (b[index] == v)
{
return index;
}
index ++;
}
return -1;
}
int ByteArray_findByteWithoutValue_from_(ByteArray *self, unsigned char v, int from)
{
unsigned char *b = self->bytes;
size_t index = from;
while (index < self->size)
{
if (b[index] != v)
{
return index;
}
index ++;
}
return -1;
}
void ByteArray_setByteWithValue_from_to_(ByteArray *self,
unsigned char v,
size_t from,
size_t to)
{
if (from > to)
{
int x = to;
to = from;
from = x;
}
if (to > ByteArray_size(self))
{
ByteArray_setSize_(self, to + 1);
}
if (to < from)
{
return;
}
if (to == from)
{
//printf("bytes[%i] = %i -> %i\n", from, self->bytes[from], v);
self->bytes[from] = v;
return;
}
memset(self->bytes + from, v, to - from + 1);
}
size_t ByteArray_count_(ByteArray *self, ByteArray *other)
{
// return number of non-overlapping occurances of other in self
size_t count = 0;
if (other->size > 0)
{
int index = ByteArray_find_from_(self, other, 0);
while (index != -1)
{
index = ByteArray_find_from_(self, other, index + other->size);
count ++;
}
}
return count;
}
void ByteArray_replaceCString_withCString_(ByteArray *self,
const char *s1,
const char *s2)
{
ByteArray *b1 = ByteArray_newWithCString_(s1);
ByteArray *b2 = ByteArray_newWithCString_(s2);
ByteArray_replace_with_(self, b1, b2);
ByteArray_free(b1);
ByteArray_free(b2);
}
void ByteArray_replace_with_output_(ByteArray *self,
ByteArray *substring,
ByteArray *other,
ByteArray *output)
{
int lastGetIndex = 0;
int getIndex = 0;
while (getIndex < (int)self->size)
{
getIndex = ByteArray_find_from_(self, substring, getIndex);
if (getIndex == -1) getIndex = self->size;
// append the non-matching chunk
ByteArray_appendBytes_size_(output, self->bytes + lastGetIndex, getIndex - lastGetIndex);
if (getIndex == (int)self->size)
{
break;
}
// append the other string
ByteArray_append_(output, other);
getIndex += substring->size;
lastGetIndex = getIndex;
}
}
void ByteArray_replaceFrom_size_with_(ByteArray *self,
size_t index,
size_t substringSize,
ByteArray *other)
{
size_t oldSize = ByteArray_size(self);
size_t otherSize = ByteArray_size(other);
size_t newSize = oldSize - substringSize + otherSize;
if (newSize > oldSize)
{
ByteArray_setSize_(self, newSize);
}
// move tail to end
{
size_t oldTailPos = index + substringSize;
size_t newTailPos = index + otherSize;
size_t tailSize = oldSize - oldTailPos;
memmove(self->bytes + newTailPos, self->bytes + oldTailPos, tailSize);
}
// copy in new chunk
memcpy(self->bytes + index, other->bytes, otherSize);
ByteArray_setSize_(self, newSize);
}
size_t ByteArray_replaceFirst_from_with_(ByteArray *self,
ByteArray *substring,
size_t start,
ByteArray *other)
{
size_t substringSize = ByteArray_size(substring);
int index = ByteArray_find_from_(self, substring, start);
if (index != -1)
{
ByteArray_replaceFrom_size_with_(self, index, substringSize, other);
return 1;
}
return 0;
}
size_t ByteArray_replace_with_(ByteArray *self, ByteArray *substring, ByteArray *other)
{
ByteArray *output = ByteArray_new();
ByteArray_replace_with_output_(self, substring, other, output);
ByteArray_copy_(self, output);
ByteArray_free(output);
return 0;
}
/*
size_t ByteArray_replace_with_2(ByteArray *self, ByteArray *substring, ByteArray *other)
{
int index;
size_t start;
size_t substringSize = ByteArray_size(substring);
size_t otherSize = ByteArray_size(other);
List *indexes = List_new();
// find match indexes
while ((index = ByteArray_find_from_(self, substring, start)) != -1)
{
List_add_(indexes, (void *)index);
start = index += substringSize;
}
size_t matchCount = List_size(indexes);
size_t oldSize = ByteArray_size(self);
size_t newSize = oldSize - ((otherSize - substringSize) * matchCount);
if (newSize > oldSize)
{
int i;
// walk match indexes in reverse order and on each one,
// copy the tail to the right and
// copy the other string
ByteArray_setSize_(self, newSize);
for (i = matchCount; i > -1; i --)
{
index = (int)List_at_(indexes, i);
}
}
else
{
// "a foo b" replace("foo", "c")
// walk match indexes in normal order and on each copy
// over the other string and the next chunk
int start = 0;
int index = ByteArray_find_from_(self, substring, start);
size_t putIndex = List_at_(indexes, i);
size_t gapSize;
int nextIndex;
for (;;)
{
index = (int)List_at_(indexes, i);
nextIndex = i < matchCount ? (int)List_at_(indexes, i + 1);
// copy in other:
// "a coo b"
memcpy(self->bytes + putIndex, other->bytes, otherSize);
putIndex += otherSize;
// copy chunk to next match:
// "a c b"
i ++;
if (i == matchCount)
{
nextIndex = oldSize;
}
memmove(self->bytes + putIndex, self->bytes , otherSize);
putIndex += gapSize;
} while (i < matchCount)
ByteArray_setSize_(self, newSize);
}
List_free(indexes);
return matchCount
}
*/
// I/O ---------------------------------------------
void ByteArray_print(ByteArray *self)
{
ByteArray_writeToCStream_(self, stdout);
}
size_t ByteArray_writeToCStream_(ByteArray *self, FILE *stream)
{
return fwrite(self->bytes, 1, self->size, stream);
}
int ByteArray_writeToFilePath_(ByteArray *self, const char *path)
{
FILE *fp = fopen(path, "w+");
if (fp)
{
size_t bytesWritten = ByteArray_writeToCStream_(self, fp);
fclose(fp);
return bytesWritten == self->size ? 0 : -1;
}
return -1;
}
int ByteArray_readFromCStream_(ByteArray *self, FILE *fp)
{
size_t bytesToRead;
size_t pos;
size_t bytesRead;
if (!fp)
{
perror("ByteArray_readFromCStream_");
return -1;
}
// get file size
pos = ftell(fp);
fseek(fp, 0, SEEK_END);
bytesToRead = ftell(fp) - pos;
fseek(fp, 0, pos);
ByteArray_setSize_(self, bytesToRead);
// read whole file into buffer
bytesRead = fread(self->bytes, 1, bytesToRead, fp);
if (bytesRead != bytesToRead)
{
printf("WARNING: read rest of file but only found %i bytes while ftell() indicated that %i were remaining - file may be directory\n",
(int)bytesRead, (int)bytesToRead);
return -1;
}
return 1;
}
int ByteArray_readFromFilePath_(ByteArray *self, const char *path)
{
FILE *fp = fopen(path, "rb");
int error;
if (!fp)
{
perror("ByteArray_readFromFilePath_");
return -1;
}
error = ByteArray_readFromCStream_(self, fp);
fclose(fp);
return error;
}
/*
unsigned char ByteArray_readLineFromCStream_(ByteArray *self, FILE *stream)
{
unsigned char readSomething = 0;
while(ferror(stream) == 0)
{
int b = fgetc(stream);
readSomething = 1;
if ( b == '\n' || b == '\r')
{
break;
}
ByteArray_appendByte_(self, b);
}
return readSomething;
}
*/
#define CHUNK_SIZE 4096
unsigned char ByteArray_readLineFromCStream_(ByteArray *self, FILE *stream)
{
unsigned char readSomething = 0;
char *s = (char *)malloc(CHUNK_SIZE);
while (fgets(s, CHUNK_SIZE, stream) != NULL)
{
char *eol1 = strchr(s, '\n');
char *eol2 = strchr(s, '\r');
readSomething = 1;
if (eol1) { *eol1 = 0; } // remove the \n return character
if (eol2) { *eol2 = 0; } // remove the \r return character
if (*s)
{
ByteArray_appendCString_(self, s);
}
if (eol1 || eol2)
{
break;
}
}
free(s);
return readSomething;
}
size_t ByteArray_readNumberOfBytes_fromCStream_(ByteArray *self, size_t size, FILE *stream)
{
size_t readSize;
size_t oldSize = ByteArray_size(self);
ByteArray_setSize_(self, oldSize + size);
readSize = fread((void *)(self->bytes + oldSize), 1, size, stream);
ByteArray_setSize_(self, oldSize + readSize);
return readSize;
}
// private utility functions ---------------------------------
int ByteArray_wrapPos_(ByteArray *self, int pos)
{
int len = self->size;
if (pos > len - 1)
{
return len;
}
if (pos < 0)
{
pos = len + pos;
if (pos < 0)
{
pos = 0;
}
}
return pos;
}
ByteArray *ByteArray_newWithFormat_(const char *format, ...)
{
ByteArray *self;
va_list ap;
va_start(ap, format);
self = ByteArray_newWithVargs_(format, ap);
va_end(ap);
return self;
}
ByteArray *ByteArray_newWithVargs_(const char *format, va_list ap)
{
ByteArray *self = ByteArray_new();
ByteArray_fromVargs_(self, format,ap);
return self;
}
ByteArray *ByteArray_fromFormat_(ByteArray *self, const char *format, ...)
{
va_list ap;
va_start(ap, format);
ByteArray_fromVargs_(self, format, ap);
va_end(ap);
return self;
}
void ByteArray_fromVargs_(ByteArray *self, const char *format, va_list ap)
{
while (*format)
{
if (*format == '%')
{
format ++;
if (*format == 's')
{
char *s = va_arg(ap, char *);
if (!s) { printf("IoState_print missing param"); return; }
ByteArray_appendCString_(self, s);
}
else if (*format == 'i' || *format == 'd')
{
int i = va_arg(ap, int);
char s[100];
snprintf(s, 100, "%i", i);
ByteArray_appendCString_(self, s);
}
else if (*format == 'f')
{
double d = va_arg(ap, double);
char s[100];
snprintf(s, 100, "%f", d);
ByteArray_appendCString_(self, s);
}
else if (*format == 'p')
{
void *p = va_arg(ap, void *);
char s[100];
snprintf(s, 100, "%p", p);
ByteArray_appendCString_(self, s);
}
// new format command for a given number adding spaces
else if (*format == '#')
{
int n, i = va_arg(ap, int);
char *s = " ";
for (n = 0; n < i; n ++)
{
ByteArray_appendCString_(self, s);
}
}
}
else
{
char s[2];
snprintf(s, 2, "%c", *format);
ByteArray_appendCString_(self, s);
}
format ++;
}
}
ByteArray *ByteArray_asNewHexStringByteArray(ByteArray *self)
{
size_t i, newSize = self->size * 2;
ByteArray *ba = ByteArray_newWithSize_(newSize);
for(i = 0; i < self->size; i ++)
{
int c = self->bytes[i];
char *s = (char *)(ba->bytes + i * 2);
if (c < 16)
{
snprintf(s, newSize, "0%x", c);
}
else
{
snprintf(s, newSize, "%x", c);
}
}
return ba;
}
// file paths --------------------------------------
unsigned char ByteArray_lastByte(ByteArray *self)
{
if (!self->size)
{
return 0;
}
return self->bytes[self->size - 1];
}
void ByteArray_appendPathCString_(ByteArray *self, const char *path)
{
char lastChar = ByteArray_lastByte(self);
int selfEndsWithSep = IsPathSeparator(lastChar);
int pathStartsWithSep = IsPathSeparator(*path);
//int pathStartsWithDoubleSep = IsPathSeparator(*path) && strlen(path) > 1 && IsPathSeparator(*(path + 1));
/*
if (pathStartsWithSep)
{
ByteArray_setCString_(self, path);
}
else
*/
if (ByteArray_size(self) != 0)
{
if (!selfEndsWithSep)
{
ByteArray_appendCString_(self, IO_PATH_SEPARATOR);
}
if (pathStartsWithSep)
{
path ++;
}
}
ByteArray_appendCString_(self, path);
ByteArray_replaceCString_withCString_(self, IO_PATH_SEPARATOR_DOT, IO_PATH_SEPARATOR);
//ByteArray_replaceCString_withCString_(self, "//", "/");
}
void ByteArray_removeLastPathComponent(ByteArray *self)
{
int pos = ByteArray_rFindCharacters_from_(self, IO_PATH_SEPARATORS, self->size - 1);
if (pos == -1) pos = 0;
ByteArray_setSize_(self, pos);
}
void ByteArray_clipBeforeLastPathComponent(ByteArray *self)
{
int pos = ByteArray_rFindCharacters_from_(self, IO_PATH_SEPARATORS, self->size - 1);
if (pos != -1)
{
ByteArray_removeSlice(self, 0, pos + 1);
}
}
ByteArray *ByteArray_lastPathComponent(ByteArray *self)
{
return ByteArray_newWithCString_(ByteArray_lastPathComponentAsCString(self));
}
char *ByteArray_lastPathComponentAsCString(ByteArray *self)
{
int pos = ByteArray_rFindCharacters_from_(self, IO_PATH_SEPARATORS, self->size-1);
char *s;
if (pos == -1)
{
return (char *)self->bytes;
}
s = (char *)(self->bytes+pos);
while ( IsPathSeparator(*s) )
{
s ++;
}
return s;
}
void ByteArray_removePathExtension(ByteArray *self)
{
int pos = ByteArray_rFindCString_from_(self, ".", self->size - 1);
if (pos != -1)
{
ByteArray_setSize_(self, pos);
}
}
ByteArray *ByteArray_pathExtension(ByteArray *self)
{
int pos = ByteArray_rFindCString_from_(self, ".", self->size - 1);
if (pos == -1)
{
return ByteArray_newWithCString_("");
}
return ByteArray_newWithCString_((char *)(self->bytes + pos + 1));
}
ByteArray *ByteArray_fileName(ByteArray *self)
{
char *s = ByteArray_lastPathComponentAsCString(self);
char *dot = strrchr(s, '.');
if (!dot)
{
return ByteArray_newWithCString_(s);
}
return ByteArray_newWithCString_size_(s, dot - s);
}
// bitwise ops ------------------------------------------------
void ByteArray_and_(ByteArray *self, ByteArray *other)
{
int l1 = ByteArray_size(self);
int l2 = ByteArray_size(other);
int i = l1 < l2 ? l1 : l2;
unsigned char *b1 = ByteArray_bytes(self);
unsigned char *b2 = ByteArray_bytes(other);
while (i)
{
*b1 = *b1 & *b2;
b1 ++;
b2 ++;
i --;
}
}
void ByteArray_or_(ByteArray *self, ByteArray *other)
{
int l1 = ByteArray_size(self);
int l2 = ByteArray_size(other);
int i = l1 < l2 ? l1 : l2;
unsigned char *b1 = ByteArray_bytes(self);
unsigned char *b2 = ByteArray_bytes(other);
while (i)
{
*b1 = *b1 | *b2;
b1 ++;
b2 ++;
i --;
}
}
void ByteArray_xor_(ByteArray *self, ByteArray *other)
{
int l1 = ByteArray_size(self);
int l2 = ByteArray_size(other);
int i = l1 < l2 ? l1 : l2;
unsigned char *b1 = ByteArray_bytes(self);
unsigned char *b2 = ByteArray_bytes(other);
while (i)
{
*b1 = *b1 ^ *b2;
b1 ++;
b2 ++;
i --;
}
}
void ByteArray_compliment(ByteArray *self)
{
int i = ByteArray_size(self);
unsigned char *b = ByteArray_bytes(self);
while (i)
{
*b = ~ (*b);
b ++;
i --;
}
}
void ByteArray_byteShiftLeft_(ByteArray *self, int s)
{
ByteArray *ba = ByteArray_new();
ByteArray_setSize_(ba, s);
ByteArray_insert_at_(self, ba, 0);
}
void ByteArray_byteShiftRight_(ByteArray *self, int s)
{
ByteArray *ba = ByteArray_new();
ByteArray_setSize_(ba, s);
ByteArray_removeSlice(self, 0, s);
ByteArray_append_(self, ba);
}
void ByteArray_bitShiftLeft_(ByteArray *self, int s)
{
int bytes = s / 8;
int bits = s % 8;
int carryBits = 8 - bits;
if (bytes > 0)
{
ByteArray_byteShiftLeft_(self, bytes);
}
else
{
ByteArray_byteShiftRight_(self, bytes);
}
{
int i = ByteArray_size(self);
unsigned char *b = ByteArray_bytes(self);
unsigned char carry = 0;
while (i)
{
*b = *b << s;
*b = *b | carry;
carry = *b >> carryBits;
b ++;
i --;
}
}
}
unsigned char ByteArray_byteAt_(ByteArray *self, size_t i)
{
if (i < self->size)
{
return self->bytes[i];
}
return 0;
}
int ByteArray_bitAt_(ByteArray *self, size_t i)
{
size_t byteIndex = i / 8;
int bitIndex = i % 8;
unsigned char byte = ByteArray_byteAt_(self, byteIndex);
return ((byte >> bitIndex) & 0x1);
}
void ByteArray_setBit_at_(ByteArray *self, int state, size_t i)
{
size_t charPos = i / 8;
if (state)
{
state = 0x1;
}
else
{
state = 0x0;
}
if (charPos < self->size)
{
unsigned char bitPos = i % 8;
unsigned char mask = 0x1 << bitPos;
if (state)
{
self->bytes[charPos] |= mask;
}
else
{
self->bytes[charPos] &= (~mask);
}
}
if (ByteArray_bitAt_(self, i) != state)
{
printf("error\n");
ByteArray_bitAt_(self, i);
}
}
// ---------------------------------------------------
float ByteArray_aveAbsFloat32From_to_(ByteArray *self, size_t from, size_t to)
{
double delta;
double ave = 0;
size_t max = ByteArray_size32(self);
if (from > max) return 0;
if (to > max) to = max;
if (from >= to) return 0;
delta = to - from;
while (from != to)
{
double v = (double)ByteArray_float32At_(self, from);
v = fabs(v);
ave += v;
from ++;
}
ave = ave ? ave / delta : 0;
return (float)ave;
}
int ByteArray_aveAbsSignedInt32From_to_(ByteArray *self, size_t from, size_t to)
{
double delta;
double ave = 0;
size_t max = ByteArray_size32(self);
if (from > max) return 0;
if (to > max) to = max;
if (from >= to) return 0;
delta = to - from;
while (from != to)
{
double v = (double)ByteArray_int32At_(self, from);
v = fabs(v);
ave += v;
from ++;
}
ave = ave ? ave / delta : 0;
return (int)ave;
}
void ByteArray_convertFloatArrayToInts(ByteArray *self)
{
size_t size = self->size / sizeof(float);
size_t n;
int32_t *i = (int32_t *)self->bytes;
float *f = (float *)self->bytes;
for (n = 0; n < size; n ++)
{
i[n] = (int32_t)(f[n] * INT_MAX);
}
}
void ByteArray_convertFloat32ArrayToInt16(ByteArray *self)
{
size_t size = self->size / sizeof(float);
size_t n;
int16_t *i = (int16_t *)self->bytes;
float *f = (float *)self->bytes;
for (n = 0; n < size; n ++)
{
i[n] = (int16_t)(f[n] * SHRT_MAX);
}
ByteArray_setSize_(self, size * sizeof(int16_t));
}
void ByteArray_convertInt16ArrayToFloat32(ByteArray *self)
{
size_t count = self->size / sizeof(int16_t);
size_t n;
int16_t *i = (int16_t *)self->bytes;
float *f = (float *)malloc(count * sizeof(float));
float d = (float)1.0 / (float)SHRT_MAX;
for (n = 0; n < count; n ++)
{
f[n] = i[n] * d;
}
ByteArray_setData_size_(self, (unsigned char *)f, count * sizeof(float));
free(f);
}
void ByteArray_float32ArrayAdd_(ByteArray *self, ByteArray *other)
{
size_t size = self->size / sizeof(float);
size_t otherSize = other->size / sizeof(float);
size_t count = size < otherSize ? size : otherSize;
float *f1 = (float *)self->bytes;
float *f2 = (float *)other->bytes;
while (count --)
{
*f1 += *f2;
f1 ++;
f2 ++;
}
}
void ByteArray_float32ArrayMultiplyScalar_(ByteArray *self, float s)
{
size_t count = self->size / sizeof(float);
float *f1 = (float *)self->bytes;
while (count --)
{
*f1 *= s;
f1 ++;
}
}
void ByteArray_zero(ByteArray *self)
{
memset(self->bytes, 0, self->size);
}
static inline int sameCompare(unsigned char *b1, unsigned char *b2, int size)
{
while (size)
{
if (*b1 != *b2)
{
return 0;
}
*b1 ++;
*b2 ++;
size --;
}
return 1;
}
int ByteArray_splitCount_(ByteArray *self, List *delims)
{
int count;
List *r = ByteArray_split_(self, delims);
count = List_size(r);
List_free(r);
return count;
}
List *ByteArray_split_(ByteArray *self, List *delims)
{
Datum d = ByteArray_asDatum(self);
List *datumDelims = List_map_(delims, (ListCollectCallback *)ByteArray_asNewDatum);
List *resultDatums = (List *)Datum_split_(&d, datumDelims);
List *results = List_map_(resultDatums, (ListCollectCallback *)Datum_asByteArray);
// free result datums
List_do_(resultDatums, (ListDoCallback *)free);
List_free(resultDatums);
// free datum delims
List_do_(datumDelims, (ListDoCallback *)free);
List_free(datumDelims);
return results;
}
void ByteArray_printBits(ByteArray *self)
{
int i, max = ByteArray_bitCount(self);
printf("%i ", (int)(self->size));
for (i = max - 1; i > - 1; i --)
{
printf("%i", ByteArray_bitAt_(self, i));
}
}
unsigned int ByteArray_bitCount(ByteArray *self)
{
return self->size * 8;
}
/*
unsigned int ByteArray_HashData_size_(const unsigned char *bytes, unsigned int size)
{
unsigned int h = 5381;
while (size-- > 0)
{
h += (h << 5); // h(i) = (h(i-1) * 33) ^ key(i)
h ^= *bytes ++;
}
return h;
}
unsigned int ByteArray_hash(ByteArray *self)
{
return ByteArray_HashData_size_(self->bytes, self->size);
}
uint32_t ByteArray_orderedHash32(ByteArray *self)
{
uint32_t hash;
memcpy(&hash, self->bytes, 4);
return hash;
}
*/
void ByteArray_removeOddIndexesOfSize_(ByteArray *self, size_t typeSize)
{
size_t di = 1;
size_t si = 2;
size_t max = self->size / typeSize;
uint8_t *b = (uint8_t *)self->bytes;
if (max == 0)
{
return;
}
while (si < max)
{
uint8_t *src = b + (si * typeSize);
uint8_t *dest = b + (di * typeSize);
memcpy(dest, src, typeSize);
//printf("copy %i <- %i \n", (int)di, (int)si);
si = si + 2;
di = di + 1;
}
ByteArray_setSize_(self, di * typeSize);
}
void ByteArray_removeEvenIndexesOfSize_(ByteArray *self, size_t typeSize)
{
size_t di = 0;
size_t si = 1;
size_t max = self->size / (typeSize);
uint8_t *b = (uint8_t *)self->bytes;
while (si < max)
{
uint8_t *src = b + (si * typeSize);
uint8_t *dest = b + (di * typeSize);
memcpy(dest, src, typeSize);
//printf("copy %i <- %i \n", (int)di, (int)si);
si = si + 2;
di = di + 1;
}
ByteArray_setSize_(self, di * typeSize);
}
void ByteArray_duplicateIndexesOfSize_(ByteArray *self, size_t typeSize)
{
size_t size = (self->size / typeSize);
if (size)
{
size_t si = size - 1;
size_t di = (size * 2) - 1;
uint8_t *b;
ByteArray_setSize_(self, self->size * 2);
b = (uint8_t *)self->bytes;
for (;;)
{
uint8_t *src;
uint8_t *dest;
src = b + si * typeSize;
dest = b + di * typeSize;
//printf("copy %i -> %i, %i \n", (int)si, (int)(di - 1), (int)di);
memcpy(dest, src, typeSize);
memcpy(dest - typeSize, src, typeSize);
if (si == 0) break;
di = di - 2;
si --;
}
}
}
int ByteArray_endsWithCString_(ByteArray *self, const char *suffix)
{
return (strcmp((char *)(self->bytes + self->size - strlen(suffix)), suffix)== 0);
}
size_t ByteArray_matchingPrefixSizeWith_(ByteArray *self, ByteArray *other)
{
Datum d1 = ByteArray_asDatum(self);
Datum d2 = ByteArray_asDatum(other);
return Datum_matchingPrefixSizeWith_(&d1, &d2);
}
// -------------------------
/*
char *string_caseInsensitiveBoyerMooreSearch(char *buffer, size_t length, char *needle, size_t needleLen)
{
register char *p;
switch (needleLen)
{
case 0:
return NULL;
case 1:
for (p = buffer; *p; p++)
{
if (toupper(*p) == toupper(*needle))
return p;
}
return NULL;
break;
}
{
register const size_t needleSafetyBouncer = needleLen - 1;
register size_t i;
register byte delta[256];
register const char *end = buffer + length;
int k;
for (i = 0; i < 256; i++)
delta[i] = needleLen;
for (i = needleLen - 1, k = 0; i >=0 ; k++, i--)
{
if (delta[(byte)toupper(needle[i])] == needleLen)
delta[(byte)toupper(needle[i])] = k;
}
for (p = buffer; p < end; )
{
for (i = needleSafetyBouncer ; ;)
{
if (toupper(p[i]) != toupper(needle[i]))
{
p+=delta[(byte)toupper(p[i])];
break;
}
if (!i--)
return p;
}
}
}
return NULL;
}
char *string_caseSensitiveBoyerMooreSearch(char *buffer, size_t length, char *needle, size_t needleLen)
{
register char *p;
switch (needleLen)
{
case 0:
return NULL;
case 1:
for (p = buffer; *p; p++)
{
if (*p == *needle)
return p;
}
return NULL;
break;
}
{
register const size_t needleSafetyBouncer = needleLen - 1;
register size_t i;
register uint8_t delta[256];
register const char *end = buffer + length;
int k;
for (i = 0; i < 256; i++)
delta[i] = needleLen;
for (i = needleLen - 1, k = 0; i >=0 ; k++, i--)
{
if (delta[(uint8_t)needle[i]] == needleLen)
delta[(uint8_t)needle[i]] = k;
}
for (p = buffer; p < end; )
{
for (i = needleSafetyBouncer ; ;)
{
if (p[i] != needle[i])
{
p+=delta[(uint8_t)p[i]];
break;
}
if (!i--)
return p;
}
}
}
return NULL;
}
*/
// cursor -------------------------------------------
/*
size_t ByteArray_bytesInCharacterAtByteOffset_(ByteArray *self, size_t offset)
{
// utf8
const char c = self->bytes[offset];
if ((c & 0xFE) == 0xFC) return 6;
if ((c & 0xFC) == 0xF8) return 5;
if ((c & 0xF8) == 0xF0) return 4;
if ((c & 0xF0) == 0xE0) return 3;
if ((c & 0xE0) == 0xC0) return 2;
if ((c & 0x80) == 0x00) return 1;
return 0;
}
size_t utf8_prev(const char *s, size_t o)
{
while (o != 0 && (s[-- o] & 0xC0) == 0x80) {}
return o;
}
size_t utf8_next(const char *s, size_t l, size_t o)
{
while (o != l && (s[++ o] & 0xC0) == 0x80) {}
return o;
}
typedef struct
{
ByteArray *array;
size_t offset; // byte offset, not character offset
} ByteArrayCursor;
ByteArrayCursor ByteArray_cursor(ByteArray *self)
{
ByteArrayCursor lc;
lc.array = self;
lc.offset = 0;
return lc;
}
void ByteArrayCursor_next(ByteArrayCursor *self)
{
size_t offset = self->p - ByteArray_bytes(self->array);
if (self->offset >= (size_t)ByteArray_sizeInBytes(self->list))
{
return;
}
self->offset += ByteArray_bytesInCharacterAtByteOffset_(self->array, self->offset);
}
IOINLINE size_t ByteArrayCursor_index(ByteArrayCursor *self)
{
return self->index;
}
IOINLINE void *ByteArrayCursor_value(ByteArrayCursor *self)
{
return List_at_(self->list, self->index);
}
*/
syntax highlighted by Code2HTML, v. 0.9.1