Skip to content

Instantly share code, notes, and snippets.

@mlfarrell
Created February 16, 2024 18:55
Show Gist options
  • Save mlfarrell/c9eb8d0834be4d119a10408e9145a7d8 to your computer and use it in GitHub Desktop.
Save mlfarrell/c9eb8d0834be4d119a10408e9145a7d8 to your computer and use it in GitHub Desktop.
////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include <string>
#include <stdexcept>
#include <cstdlib>
#include "GrowableArray.h"
#include "base64.h"
#include "PlistReader.h"
#include "PlistBuilder.h"
using namespace std;
namespace vutil
{
GrowableArray::GrowableArray()
{
elemSize = 1;
growSize = 1024;
allocation = 0;
data = nullptr;
count = 0;
}
GrowableArray::GrowableArray(const GrowableArray *from) : GrowableArray(from->data, from->count, from->elemSize, 0)
{
}
GrowableArray::GrowableArray(int elementSz, int cap)
{
elemSize = elementSz;
growSize = 1024;
allocation = cap ? cap : growSize;
data = malloc(elemSize*allocation);
count = 0;
}
GrowableArray::GrowableArray(const void *array, int arraySz, int elementSz, int extraCapacity)
{
elemSize = elementSz;
growSize = 1024;
allocation = arraySz+extraCapacity;
data = malloc(elemSize*allocation);
memcpy(data, array, arraySz*elemSize);
count = arraySz;
}
GrowableArray::GrowableArray(const unsigned char *base64Str)
{
int len = 0;
GrowableArray decoded(1);
base64_decode(base64Str, &decoded);
len = decoded.getCount();
elemSize = 1;
growSize = 1024;
allocation = len;
data = malloc(elemSize*allocation);
memcpy(data, decoded.data, len*elemSize);
count = len;
}
GrowableArray::GrowableArray(void *array, int arraySz, int elementSz, InitMode noCopy)
{
elemSize = elementSz;
growSize = 1024;
data = array;
count = arraySz;
}
GrowableArray::~GrowableArray()
{
if(data)
free(data);
}
void GrowableArray::archive(vutil::PlistBuilder &builder)
{
builder.beginArchivingClass({ "GrowableArray", "NSObject" });
builder.archiveIntForKey("count", count);
builder.archiveIntForKey("elemSize", elemSize);
builder.archiveIntForKey("growSize", growSize);
builder.archiveDataForKey("arrayData", data, elemSize*count);
}
void GrowableArray::unarchive(vutil::PlistReader &reader)
{
count = reader.intForKey("count");
elemSize = reader.intForKey("elemSize");
growSize = reader.intForKey("growSize");
if(data)
throw vgl_runtime_error("invalid repeated unarchive of object");
allocation = count;
data = malloc(elemSize*allocation);
if(count > 0)
{
auto loadedData = reader.dataForKey("arrayData");
memcpy(data, loadedData->data, elemSize*allocation);
}
}
void GrowableArray::shrinkToSize(int sz)
{
bool realloc = false;
if(count-sz > growSize)
realloc = true;
shrinkToSize(sz, realloc, growSize);
}
void GrowableArray::shrinkToSize(int sz, bool forceRealloc, int extraCapacity)
{
bool realloc = forceRealloc;
if(!forceRealloc)
{
if(count-sz > growSize)
realloc = true;
}
if(sz > count || sz < 0)
throw vgl_runtime_error("Attempting to shrink to a larger or invalid size");
count = sz;
if(realloc)
{
data = ::realloc(data, (count+extraCapacity)*elemSize);
allocation = count+extraCapacity;
}
}
void *GrowableArray::addElements(int num)
{
count += num;
if(count > allocation)
{
data = realloc(data, (count+growSize)*elemSize);
allocation = count+growSize;
}
return ((char *)data)+elemSize*(count-num);
}
void *GrowableArray::elementAtIndex(int index)
{
return ((char *)data)+elemSize*(index);
}
void *GrowableArray::moveData()
{
void *tmp = data;
data = nullptr;
return tmp;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment