Files
2024-05-18 23:53:26 +08:00

380 lines
11 KiB
C++

/**
* @file kArray1.cpp
*
* @internal
* Copyright (C) 2005-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#include <kApi/Data/kArray1.h>
#include <kApi/Data/kArrayProvider.h>
#include <kApi/Data/kCollection.h>
#include <kApi/Io/kSerializer.h>
kBeginClassEx(k, kArray1)
//serialization versions
kAddPrivateVersionEx(kArray1, "kdat5", "5.0.0.0", "24-1", WriteDat5V1, ReadDat5V1)
kAddPrivateVersionEx(kArray1, "kdat6", "5.7.1.0", "kArray1-0", WriteDat6V0, ReadDat6V0)
//special constructors
kAddPrivateFrameworkConstructor(kArray1, ConstructFramework)
//virtual methods
kAddPrivateVMethod(kArray1, kObject, VRelease)
kAddPrivateVMethod(kArray1, kObject, VDisposeItems)
kAddPrivateVMethod(kArray1, kObject, VClone)
kAddPrivateVMethod(kArray1, kObject, VHasShared)
kAddPrivateVMethod(kArray1, kObject, VSize)
kAddPrivateVMethod(kArray1, kObject, VAllocTraits)
//collection interface
kAddInterface(kArray1, kCollection)
kAddPrivateIVMethod(kArray1, kCollection, VGetIterator, GetIterator)
kAddIVMethod(kArray1, kCollection, VItemType, ItemType)
kAddIVMethod(kArray1, kCollection, VCount, Count)
kAddPrivateIVMethod(kArray1, kCollection, VHasNext, HasNext)
kAddPrivateIVMethod(kArray1, kCollection, VNext, Next)
//array provider interface
kAddInterface(kArray1, kArrayProvider)
kAddPrivateIVMethod(kArray1, kArrayProvider, VConstructDefault, ConstructDefaultEx)
kAddPrivateIVMethod(kArray1, kArrayProvider, VImitate, Imitate)
kAddPrivateIVMethod(kArray1, kArrayProvider, VAssign, Assign)
kAddIVMethod(kArray1, kArrayProvider, VItemType, ItemType)
kAddIVMethod(kArray1, kArrayProvider, VCount, Count)
kAddIVMethod(kArray1, kArrayProvider, VData, Data)
kAddIVMethod(kArray1, kArrayProvider, VDataSize, DataSize)
kAddIVMethod(kArray1, kArrayProvider, VDataAlloc, DataAlloc)
kEndClassEx()
kFx(kStatus) kArray1_ConstructEx(kArray1* array, kType itemType, kSize length, kAlloc allocator, kAlloc valueAllocator, kMemoryAlignment valueAlignment)
{
kAlloc alloc = kAlloc_Fallback(allocator);
kAlloc valueAlloc = kAlloc_Fallback(valueAllocator);
kStatus status;
kCheck(kAlloc_GetObject(alloc, kTypeOf(kArray1), array));
if (!kSuccess(status = xkArray1_Init(*array, kTypeOf(kArray1), itemType, length, alloc, valueAlloc, valueAlignment)))
{
kAlloc_FreeRef(alloc, array);
}
return status;
}
kFx(kStatus) kArray1_Construct(kArray1* array, kType itemType, kSize length, kAlloc allocator)
{
return kArray1_ConstructEx(array, itemType, length, allocator, allocator);
}
kFx(kStatus) xkArray1_ConstructFramework(kArray1* array, kAlloc allocator)
{
return kArray1_ConstructEx(array, kNULL, 0, allocator, allocator);
}
kFx(kStatus) xkArray1_ConstructDefaultEx(kArray1* array, kAlloc objectAlloc, kAlloc valueAlloc)
{
return kArray1_ConstructEx(array, kNULL, 0, objectAlloc, valueAlloc);
}
kFx(kStatus) xkArray1_Init(kArray1 array, kType classType, kType itemType, kSize length, kAlloc alloc, kAlloc valueAlloc, kMemoryAlignment alignment)
{
kObjR(kArray1, array);
kType resolvedItemType = kIsNull(itemType) ? kTypeOf(kVoid) : itemType;
kStatus status = kOK;
kCheck(kObject_Init(array, classType, alloc));
obj->valueAlloc = valueAlloc;
obj->itemType = resolvedItemType;
obj->itemSize = kType_Size(obj->itemType);
obj->allocSize = 0;
obj->items = kNULL;
obj->length = 0;
obj->isAttached = kFALSE;
obj->alignment = alignment;
kTry
{
kTest(xkArray1_Realloc(array, length));
}
kCatch(&status)
{
xkArray1_VRelease(array);
kEndCatch(status);
}
return kOK;
}
kFx(kStatus) xkArray1_VClone(kArray1 array, kArray1 source, kAlloc valueAlloc, kObject context)
{
kObj(kArray1, array);
obj->valueAlloc = valueAlloc;
kCheck(xkArray1_Imitate(array, source));
kCheck(kCloneItems(obj->itemType, kArray1_DataAlloc(array), obj->items, kArray1_DataAlloc(source), kArray1_Data(source), obj->length, context, kObject_Alloc(array), valueAlloc));
return kOK;
}
kFx(kStatus) xkArray1_VRelease(kArray1 array)
{
kObj(kArray1, array);
if (!obj->isAttached)
{
kCheck(kAlloc_Free(kArray1_DataAlloc(array), obj->items));
}
kCheck(kObject_VRelease(array));
return kOK;
}
kFx(kStatus) xkArray1_VDisposeItems(kArray1 array)
{
kObj(kArray1, array);
kCheck(kDisposeItems(obj->itemType, obj->items, obj->length));
return kOK;
}
kFx(kBool) xkArray1_VHasShared(kArray1 array)
{
kObj(kArray1, array);
return kObject_IsShared(array) || kHasSharedItems(obj->itemType, obj->items, obj->length);
}
kFx(kSize) xkArray1_VSize(kArray1 array)
{
kObj(kArray1, array);
kSize dataSize = (!obj->isAttached) ? obj->allocSize : kArray1_DataSize(array);
kSize size = sizeof(kArray1Class) + dataSize;
size += kMeasureItems(obj->itemType, obj->items, obj->length);
return size;
}
kFx(kAllocTrait) xkArray1_VAllocTraits(kArray1 array)
{
kObj(kArray1, array);
return kAlloc_Traits(kObject_Alloc(array)) | kAlloc_Traits(kArray1_DataAlloc(array)) | kEnumerateAllocTraits(obj->itemType, obj->items, obj->length);
}
kFx(kStatus) xkArray1_WriteDat5V1(kArray1 array, kSerializer serializer)
{
kObj(kArray1, array);
kTypeVersion itemVersion;
kCheck(kSerializer_WriteSize(serializer, obj->length));
kCheck(kSerializer_WriteType(serializer, obj->itemType, &itemVersion));
kCheck(kSerializer_WriteItems(serializer, obj->itemType, itemVersion, obj->items, obj->length));
return kOK;
}
kFx(kStatus) xkArray1_ReadDat5V1(kArray1 array, kSerializer serializer)
{
kObj(kArray1, array);
kSize length = 0;
kTypeVersion itemVersion;
kType itemType = kNULL;
kCheck(kSerializer_ReadSize(serializer, &length));
kCheck(kSerializer_ReadType(serializer, &itemType, &itemVersion));
kCheck(kArray1_Allocate(array, itemType, length));
kCheck(kSerializer_ReadItems(serializer, itemType, itemVersion, obj->items, length));
return kOK;
}
kFx(kStatus) xkArray1_WriteDat6V0(kArray1 array, kSerializer serializer)
{
kObj(kArray1, array);
kTypeVersion itemVersion;
kCheck(kSerializer_WriteType(serializer, obj->itemType, &itemVersion));
kCheck(kSerializer_WriteSize(serializer, obj->length));
kCheck(kSerializer_WriteItems(serializer, obj->itemType, itemVersion, obj->items, obj->length));
return kOK;
}
kFx(kStatus) xkArray1_ReadDat6V0(kArray1 array, kSerializer serializer)
{
kObj(kArray1, array);
kType itemType = kNULL;
kTypeVersion itemVersion;
kSize length = 0;
kCheck(kSerializer_ReadType(serializer, &itemType, &itemVersion));
kCheck(kSerializer_ReadSize(serializer, &length));
kCheck(kArray1_Allocate(array, itemType, length));
kCheck(kSerializer_ReadItems(serializer, itemType, itemVersion, obj->items, length));
return kOK;
}
kFx(kStatus) xkArray1_Realloc(kArray1 array, kSize length)
{
kObj(kArray1, array);
kSize newSize = kMax_(obj->allocSize, length*obj->itemSize);
if (newSize > obj->allocSize)
{
void* oldItems = obj->items;
void* newItems = kNULL;
kCheck(kAlloc_Get(kArray1_DataAlloc(array), newSize, &newItems, obj->alignment));
obj->items = newItems;
obj->allocSize = newSize;
kCheck(kAlloc_Free(kArray1_DataAlloc(array), oldItems));
}
if (kType_IsReference(obj->itemType))
{
kMemSet(obj->items, 0, obj->itemSize*length);
}
obj->length = length;
return kOK;
}
kFx(kStatus) kArray1_Allocate(kArray1 array, kType itemType, kSize length)
{
kObj(kArray1, array);
if (obj->isAttached)
{
obj->items = kNULL;
obj->isAttached = kFALSE;
}
//if the value allocator is specialized, and we are changing from value type to ref type (or vice versa), reallocate
if ((kObject_Alloc(array) != obj->valueAlloc) && (kType_IsValue(itemType) != kType_IsValue(obj->itemType)))
{
kCheck(kAlloc_FreeRef(kArray1_DataAlloc(array), &obj->items));
obj->allocSize = 0;
}
obj->itemType = kIsNull(itemType) ? kTypeOf(kVoid) : itemType;
obj->itemSize = kType_Size(obj->itemType);
obj->length = 0;
kCheck(xkArray1_Realloc(array, length));
return kOK;
}
kFx(kStatus) kArray1_Attach(kArray1 array, void* items, kType itemType, kSize length)
{
kObj(kArray1, array);
if (!obj->isAttached)
{
kCheck(kAlloc_FreeRef(kArray1_DataAlloc(array), &obj->items));
}
obj->itemType = kIsNull(itemType) ? kTypeOf(kVoid) : itemType;
obj->itemSize = kType_Size(obj->itemType);
obj->allocSize = 0;
obj->items = items;
obj->length = length;
obj->isAttached = kTRUE;
return kOK;
}
kFx(kStatus) xkArray1_Imitate(kArray1 array, kArray1 source)
{
return kArray1_Allocate(array, kArray1_ItemType(source), kArray1_Length(source));
}
kFx(kStatus) xkArray1_Assign(kArray1 array, kArray1 source, kObject context)
{
kObj(kArray1, array);
kObjN(kArray1, sourceObj, source);
kCheck(xkArray1_Imitate(array, source));
kCheck(kCopyItems(obj->itemType, kArray1_DataAlloc(array), obj->items, kArray1_DataAlloc(source), sourceObj->items, obj->length, context));
return kOK;
}
kFx(kStatus) kArray1_Zero(kArray1 array)
{
kObj(kArray1, array);
kCheckArgs(!kAlloc_IsForeign(kArray1_DataAlloc(array)));
kCheck(kZeroItems(obj->itemType, obj->items, obj->length));
return kOK;
}
kFx(kStatus) kArray1_SetItem(kArray1 array, kSize index, const void* item)
{
kObj(kArray1, array);
kAssert(!kAlloc_IsForeign(kArray1_DataAlloc(array)));
kCheckArgs(index < obj->length);
kValue_Import(obj->itemType, kArray1_DataAt(array, (kSSize)index), item);
return kOK;
}
kFx(kStatus) kArray1_Item(kArray1 array, kSize index, void* item)
{
kObj(kArray1, array);
kAssert(!kAlloc_IsForeign(kArray1_DataAlloc(array)));
kCheckArgs(index < obj->length);
kItemCopy(item, kArray1_DataAt(array, (kSSize)index), obj->itemSize);
return kOK;
}
kFx(kIterator) xkArray1_GetIterator(kArray1 array)
{
kObj(kArray1, array);
return obj->items;
}
kFx(kBool) xkArray1_HasNext(kArray1 array, kIterator iterator)
{
kObj(kArray1, array);
void* end = (kByte*)obj->items + obj->length*obj->itemSize;
return (iterator != end);
}
kFx(void*) xkArray1_Next(kArray1 array, kIterator* iterator)
{
kObj(kArray1, array);
void* next = *iterator;
*iterator = (kByte*)*iterator + obj->itemSize;
return next;
}