822 lines
20 KiB
C++
822 lines
20 KiB
C++
/**
|
|||
|
|
* @file kAssembly.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/kAssembly.h>
|
||
|
|
#include <kApi/kApiLib.h>
|
||
|
|
#include <kApi/Data/kArrayList.h>
|
||
|
|
#include <kApi/Data/kMap.h>
|
||
|
|
#include <kApi/Threads/kLock.h>
|
||
|
|
#include <kApi/Utils/kEvent.h>
|
||
|
|
|
||
|
|
kBeginFullClassEx(k, kAssembly)
|
||
|
|
kAddPrivateVMethod(kAssembly, kObject, VRelease)
|
||
|
|
kEndFullClassEx()
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_InitStatic()
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_ConstructEx(&sobj->lock, xkLOCK_OPTION_PRIORITY_INHERITANCE, kNULL));
|
||
|
|
|
||
|
|
kCheck(kEvent_Construct(&sobj->onLoad, kNULL));
|
||
|
|
kCheck(kEvent_Construct(&sobj->onUnload, kNULL));
|
||
|
|
kCheck(kEvent_Construct(&sobj->onUnloaded, kNULL));
|
||
|
|
|
||
|
|
//kAlloc and kAssembly have a mutual static dependency; this line breaks the dependency,
|
||
|
|
//allowing kAlloc to perform part of its initialization before kAssembly and part after
|
||
|
|
kCheck(xkAlloc_EndInitStatic());
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_ReleaseStatic()
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kDestroyRef(&sobj->lock));
|
||
|
|
|
||
|
|
kCheck(kDestroyRef(&sobj->onLoad));
|
||
|
|
kCheck(kDestroyRef(&sobj->onUnload));
|
||
|
|
kCheck(kDestroyRef(&sobj->onUnloaded));
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddAssembly(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObj(kAssembly, assembly);
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
if (kSuccess(kAssembly_Find(obj->name, kNULL)))
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: assembly %s already exsists", obj->name);
|
||
|
|
kTest(kERROR_ALREADY_EXISTS);
|
||
|
|
}
|
||
|
|
|
||
|
|
kTest(xkSysMemReallocList(&sobj->assemblies, sobj->assemblyCount, sizeof(kAssembly),
|
||
|
|
&sobj->assemblyCapacity, xkASSEMBLY_INITIAL_ASSEMBLY_CAPACITY, sobj->assemblyCount+1));
|
||
|
|
|
||
|
|
sobj->assemblies[sobj->assemblyCount++] = assembly;
|
||
|
|
|
||
|
|
kTest(kEvent_Notify(sobj->onLoad, assembly, kNULL));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_RemoveAssembly(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Notify(sobj->onUnload, assembly, kNULL));
|
||
|
|
|
||
|
|
for (i = 0; i < sobj->assemblyCount; ++i)
|
||
|
|
{
|
||
|
|
if (sobj->assemblies[i] == assembly)
|
||
|
|
{
|
||
|
|
kTest(kMemMove(&sobj->assemblies[i], &sobj->assemblies[i+1], sizeof(kAssembly)*(sobj->assemblyCount-i-1)));
|
||
|
|
sobj->assemblyCount--;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sobj->assemblyCount == 0)
|
||
|
|
{
|
||
|
|
kTest(xkSysMemFree(sobj->assemblies));
|
||
|
|
sobj->assemblyCapacity = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_AddLoadHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Add(sobj->onLoad, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_RemoveLoadHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Remove(sobj->onLoad, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_AddUnloadHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Add(sobj->onUnload, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_RemoveUnloadHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Remove(sobj->onUnload, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_AddUnloadedHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Add(sobj->onUnloaded, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_RemoveUnloadedHandler(kCallbackFx function, kPointer receiver)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kEvent_Remove(sobj->onUnloaded, function, receiver));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_Enumerate(kArrayList assemblies)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kArrayList_Import(assemblies, sobj->assemblies, kTypeOf(kAssembly), sobj->assemblyCount));
|
||
|
|
kTest(kShareItems(kTypeOf(kAssembly), kArrayList_DataT(assemblies, kAssembly), kArrayList_Count(assemblies)));
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_Find(const kChar* name, kAssembly* assembly)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
kBool found = kFALSE;
|
||
|
|
|
||
|
|
kCheck(kLock_Enter(sobj->lock));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
for (kSize i = 0; i < sobj->assemblyCount; ++i)
|
||
|
|
{
|
||
|
|
kAssembly assemblyAt = sobj->assemblies[i];
|
||
|
|
|
||
|
|
if (kStrEquals(kAssembly_Name(assemblyAt), name))
|
||
|
|
{
|
||
|
|
if (!kIsNull(assembly))
|
||
|
|
{
|
||
|
|
kShareRef(assembly, assemblyAt);
|
||
|
|
}
|
||
|
|
|
||
|
|
found = kTRUE;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kLock_Exit(sobj->lock);
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return (found) ? kOK : kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_ConstructInternal(kAssembly* assembly, kAssembly* reference, const kChar* name, kVersion version, kVersion platformVersion)
|
||
|
|
{
|
||
|
|
kAssembly output = kNULL;
|
||
|
|
kStatus status;
|
||
|
|
|
||
|
|
kCheck(xkSysMemAlloc(sizeof(kAssemblyClass), &output));
|
||
|
|
|
||
|
|
if (!kSuccess(status = xkAssembly_Init(output, kNULL, kNULL, reference, name, version, platformVersion)))
|
||
|
|
{
|
||
|
|
kCheck(xkSysMemFree(output));
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
*assembly = output;
|
||
|
|
*reference = output;
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_Init(kAssembly assembly, kType type, kAlloc allocator, kAssembly* reference, const kChar* name, kVersion version, kVersion platformVersion)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kStatus status;
|
||
|
|
|
||
|
|
kCheck(kObject_Init(assembly, type, allocator));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
if (!kSuccess(status = kStrCopy(obj->name, kCountOf(obj->name), name)))
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: name (%s) too long (capacity=%u).", name, kCountOf(obj->name));
|
||
|
|
kThrow(status);
|
||
|
|
}
|
||
|
|
|
||
|
|
obj->version = version;
|
||
|
|
obj->platformVersion = platformVersion;
|
||
|
|
obj->selfReference = reference;
|
||
|
|
}
|
||
|
|
kCatch(&status)
|
||
|
|
{
|
||
|
|
kObject_VRelease(assembly);
|
||
|
|
kEndCatch(status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_VRelease(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kAssembly* reference = obj->selfReference;
|
||
|
|
|
||
|
|
if (obj->isRegistered)
|
||
|
|
{
|
||
|
|
kCheck(xkAssembly_RemoveAssembly(assembly));
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(kObject_Destroy(obj->typeMap));
|
||
|
|
|
||
|
|
kCheck(xkAssembly_ReleaseTypes(assembly));
|
||
|
|
kCheck(xkAssembly_ReleaseDependencies(assembly));
|
||
|
|
|
||
|
|
kCheck(kObject_VRelease(assembly));
|
||
|
|
|
||
|
|
*reference = kNULL;
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddDependency(kAssembly assembly, xkAssemblyConstructFx depend)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
|
||
|
|
kCheck(xkSysMemReallocList(&obj->dependCalls, obj->dependCallCount, sizeof(xkAssemblyConstructFx),
|
||
|
|
&obj->dependCallCapacity, xkASSEMBLY_INITIAL_DEPEND_CAPACITY, obj->dependCallCount+1));
|
||
|
|
|
||
|
|
obj->dependCalls[obj->dependCallCount++] = depend;
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddType(kAssembly assembly, xkAssemblyRegisterFx call, const kChar* name)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
|
||
|
|
kCheck(xkSysMemReallocList(&obj->regCalls, obj->regCallCount, sizeof(xkAssemblyRegCallInfo),
|
||
|
|
&obj->regCallCapacity, xkASSEMBLY_INITIAL_TYPE_CAPACITY, obj->regCallCount+1));
|
||
|
|
|
||
|
|
obj->regCalls[obj->regCallCount].call = call;
|
||
|
|
kStrCopy(obj->regCalls[obj->regCallCount].name, kCountOf(obj->regCalls[obj->regCallCount].name), name);
|
||
|
|
obj->regCalls[obj->regCallCount].priority = k16S_MAX;
|
||
|
|
|
||
|
|
obj->regCallCount++;
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddPriority(kAssembly assembly, xkAssemblyRegisterFx call, k32u priority)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
for (i = 0; i < obj->regCallCount; ++i)
|
||
|
|
{
|
||
|
|
if (obj->regCalls[i].call == call)
|
||
|
|
{
|
||
|
|
obj->regCalls[i].priority = priority;
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_Finalize(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
|
||
|
|
kCheck(xkAssembly_InitDependencies(assembly));
|
||
|
|
kCheck(xkAssembly_InitTypes(assembly));
|
||
|
|
kCheck(xkAssembly_MapTypes(assembly));
|
||
|
|
|
||
|
|
kCheck(xkAssembly_AddAssembly(assembly));
|
||
|
|
|
||
|
|
obj->isRegistered = kTRUE;
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_InitDependencies(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSize callCount = obj->dependCallCount;
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
kCheck(xkSysMemAlloc(callCount*sizeof(kAssembly), &obj->dependencies));
|
||
|
|
|
||
|
|
for (i = 0; i < callCount; ++i)
|
||
|
|
{
|
||
|
|
kCheck(obj->dependCalls[i](&obj->dependencies[i]));
|
||
|
|
obj->dependencyCount++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_ReleaseDependencies(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSSize count = (kSSize)obj->dependencyCount;
|
||
|
|
kSSize i;
|
||
|
|
|
||
|
|
for (i = count-1; i >= 0; --i)
|
||
|
|
{
|
||
|
|
kCheck(kDestroyRef(&obj->dependencies[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(xkSysMemFree(obj->dependencies));
|
||
|
|
kCheck(xkSysMemFree(obj->dependCalls));
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_ReorderType(kAssembly assembly, const kChar* dependentOn)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSize dependentIndex = 0;
|
||
|
|
|
||
|
|
kCheck(xkAssembly_FindRegCall(assembly, dependentOn, &dependentIndex));
|
||
|
|
|
||
|
|
if (dependentIndex > obj->nowRegistering)
|
||
|
|
{
|
||
|
|
xkAssemblyRegCallInfo callInfo = obj->regCalls[obj->nowRegistering];
|
||
|
|
|
||
|
|
kMemMove(&obj->regCalls[obj->nowRegistering], &obj->regCalls[obj->nowRegistering+1],
|
||
|
|
(dependentIndex-obj->nowRegistering)*sizeof(callInfo));
|
||
|
|
|
||
|
|
obj->regCalls[dependentIndex] = callInfo;
|
||
|
|
|
||
|
|
obj->reordered = kTRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_FindRegCall(kAssembly assembly, const kChar* name, kSize* index)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
for (i = 0; i < obj->regCallCount; ++i)
|
||
|
|
{
|
||
|
|
if (kStrEquals(obj->regCalls[i].name, name))
|
||
|
|
{
|
||
|
|
*index = i;
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_InitTypes(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
xkAssemblyRegCallInfo* regCalls = obj->regCalls;
|
||
|
|
kSize count = obj->regCallCount;
|
||
|
|
kSize typeCount;
|
||
|
|
kStatus status;
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
kCheck(xkSysMemAlloc(count*sizeof(kType), &obj->types));
|
||
|
|
|
||
|
|
i = 0;
|
||
|
|
while (i < count)
|
||
|
|
{
|
||
|
|
typeCount = obj->typeCount;
|
||
|
|
obj->nowRegistering = i;
|
||
|
|
obj->reordered = kFALSE;
|
||
|
|
|
||
|
|
status = regCalls[i].call(assembly, regCalls[i].name);
|
||
|
|
|
||
|
|
if (!kSuccess(status) && (obj->typeCount > typeCount))
|
||
|
|
{
|
||
|
|
kCheck(xkType_VRelease(obj->types[typeCount]));
|
||
|
|
kCheck(xkSysMemFree(obj->types[typeCount]));
|
||
|
|
|
||
|
|
obj->typeCount--;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!obj->reordered)
|
||
|
|
{
|
||
|
|
kCheck(status);
|
||
|
|
kCheck(xkType_SetInitPriority(obj->types[typeCount], regCalls[typeCount].priority));
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < obj->typeCount; ++i)
|
||
|
|
{
|
||
|
|
xkObject_CastRaw(obj->types[i])->type = kTypeOf(kType);
|
||
|
|
}
|
||
|
|
|
||
|
|
xkObject_CastRaw(assembly)->type = kTypeOf(kAssembly);
|
||
|
|
|
||
|
|
kCheck(xkAssembly_SortTypes(assembly));
|
||
|
|
|
||
|
|
for (i = 0; i < obj->typeCount; ++i)
|
||
|
|
{
|
||
|
|
kCheck(xkType_Prepare(obj->types[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < obj->typeCount; ++i)
|
||
|
|
{
|
||
|
|
kCheck(xkType_RunStaticInit(obj->types[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_ReleaseTypes(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kSSize count = (k32s) obj->typeCount;
|
||
|
|
kSSize i;
|
||
|
|
|
||
|
|
for (i = count-1; i >= 0; --i)
|
||
|
|
{
|
||
|
|
kCheck(xkType_RunStaticRelease(obj->types[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!kIsNull(kAssemblyOf(kApiLib)) && !kIsNull(xkTypeVar(kAssembly)) && kType_StaticInitialized(kTypeOf(kAssembly)) && obj->isRegistered)
|
||
|
|
{
|
||
|
|
kStaticObj(kAssembly);
|
||
|
|
|
||
|
|
kEvent_Notify(sobj->onUnloaded, assembly, kNULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = count-1; i >= 0; --i)
|
||
|
|
{
|
||
|
|
kCheck(xkType_VRelease(obj->types[i]));
|
||
|
|
kCheck(xkSysMemFree(obj->types[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(xkSysMemFree(obj->types));
|
||
|
|
kCheck(xkSysMemFree(obj->regCalls));
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int kAssembly_TypeSortComparator(const void* a, const void* b)
|
||
|
|
{
|
||
|
|
return (k32s)xkType_Priority(*(kType*)a) - (k32s)xkType_Priority(*(kType*)b);
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_SortTypes(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
|
||
|
|
qsort(obj->types, obj->typeCount, sizeof(kType), kAssembly_TypeSortComparator);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_MapTypes(kAssembly assembly)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kStatus status = kOK;
|
||
|
|
|
||
|
|
kCheck(kMap_Construct(&obj->typeMap, kTypeOf(kTypeName), kTypeOf(kType), 0, kNULL));
|
||
|
|
|
||
|
|
for (kSize i = 0; i < obj->typeCount; ++i)
|
||
|
|
{
|
||
|
|
if (!kSuccess(status = kMap_AddT(obj->typeMap, kType_Name(obj->types[i]), &obj->types[i])))
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: Same type name (%s) registered multiple times?", kType_Name(obj->types[i]));
|
||
|
|
kCheck(status);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddValue(kAssembly assembly, kType* type, const kChar* name, kType base, const kChar* baseName, kSize size, kTypeFlags flags)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kType output = kNULL;
|
||
|
|
kStatus status;
|
||
|
|
|
||
|
|
if (kIsNull(base) && !kStrEquals(baseName, "kNull"))
|
||
|
|
{
|
||
|
|
if (kSuccess(xkAssembly_ReorderType(assembly, baseName)))
|
||
|
|
{
|
||
|
|
return kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: Forgot to register base (%s) for type (%s) with kAddType?", baseName, name);
|
||
|
|
kCheck(kERROR_STATE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(xkType_Construct(&output, type, name, assembly, flags, size, 0));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(xkType_SetBase(output, base));
|
||
|
|
kTest(xkType_InitMethods(output));
|
||
|
|
kTest(xkType_InitVTable(output));
|
||
|
|
kTest(xkType_InitInterfaces(output));
|
||
|
|
|
||
|
|
obj->types[obj->typeCount++] = output;
|
||
|
|
*type = output;
|
||
|
|
}
|
||
|
|
kCatch(&status)
|
||
|
|
{
|
||
|
|
xkType_VRelease(output);
|
||
|
|
xkSysMemFree(output);
|
||
|
|
kEndCatch(status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddClass(kAssembly assembly, kType* type, const kChar* name, kType base, const kChar* baseName, kSize innerSize)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kType output = kNULL;
|
||
|
|
kStatus status;
|
||
|
|
|
||
|
|
if (kIsNull(base) && !kStrEquals(baseName, "kNull"))
|
||
|
|
{
|
||
|
|
if (kSuccess(xkAssembly_ReorderType(assembly, baseName)))
|
||
|
|
{
|
||
|
|
return kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: Forgot to register base (%s) for type (%s) with kAddType?", baseName, name);
|
||
|
|
kCheck(kERROR_STATE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(xkType_Construct(&output, type, name, assembly, kTYPE_FLAGS_CLASS, sizeof(kPointer), innerSize));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(xkType_SetBase(output, base));
|
||
|
|
kTest(xkType_InitMethods(output));
|
||
|
|
kTest(xkType_InitVTable(output));
|
||
|
|
kTest(xkType_InitInterfaces(output));
|
||
|
|
|
||
|
|
obj->types[obj->typeCount++] = output;
|
||
|
|
*type = output;
|
||
|
|
}
|
||
|
|
kCatch(&status);
|
||
|
|
{
|
||
|
|
xkType_VRelease(output);
|
||
|
|
xkSysMemFree(output);
|
||
|
|
kEndCatch(status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_AddInterface(kAssembly assembly, kType* type, const kChar* name, kType base, const kChar* baseName)
|
||
|
|
{
|
||
|
|
kObjR(kAssembly, assembly);
|
||
|
|
kType output = kNULL;
|
||
|
|
kStatus status;
|
||
|
|
|
||
|
|
if (kIsNull(base) && !kStrEquals(baseName, "kNull"))
|
||
|
|
{
|
||
|
|
if (kSuccess(xkAssembly_ReorderType(assembly, baseName)))
|
||
|
|
{
|
||
|
|
return kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kLogf("kAssembly: Forgot to register base interface (%s) for type (%s) with kAddType?", baseName, name);
|
||
|
|
kCheck(kERROR_STATE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kCheck(xkType_Construct(&output, type, name, assembly, kTYPE_FLAGS_INTERFACE, sizeof(kPointer), 0));
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(xkType_SetBase(output, base));
|
||
|
|
kTest(xkType_InitVTable(output));
|
||
|
|
|
||
|
|
obj->types[obj->typeCount++] = output;
|
||
|
|
*type = output;
|
||
|
|
}
|
||
|
|
kCatch(&status)
|
||
|
|
{
|
||
|
|
xkType_VRelease(output);
|
||
|
|
xkSysMemFree(output);
|
||
|
|
kEndCatch(status);
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_FindType(kAssembly assembly, const kChar* name, kType* type)
|
||
|
|
{
|
||
|
|
if (!kIsNull(assembly))
|
||
|
|
{
|
||
|
|
kObj(kAssembly, assembly);
|
||
|
|
|
||
|
|
return kMap_FindT(obj->typeMap, name, type);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kArrayList assemblies = kNULL;
|
||
|
|
kBool found = kFALSE;
|
||
|
|
kSize i = 0;
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kArrayList_Construct(&assemblies, kTypeOf(kAssembly), 0, kAlloc_App()));
|
||
|
|
|
||
|
|
kTest(kAssembly_Enumerate(assemblies));
|
||
|
|
|
||
|
|
while (!found && (i < kArrayList_Count(assemblies)))
|
||
|
|
{
|
||
|
|
kAssembly assemblyAt = kArrayList_AsT(assemblies, i++, kAssembly);
|
||
|
|
|
||
|
|
found = kSuccess(kAssembly_FindType(assemblyAt, name, type));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kDisposeRef(&assemblies);
|
||
|
|
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
|
||
|
|
return (found) ? kOK : kERROR_NOT_FOUND;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkAssembly_FindDerivedTypesInAssembly(kAssembly assembly, kType base, kArrayList types)
|
||
|
|
{
|
||
|
|
kObj(kAssembly, assembly);
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
for (i = 0; i < kAssembly_TypeCount(assembly); ++i)
|
||
|
|
{
|
||
|
|
kType type = kAssembly_TypeAt(assembly, i);
|
||
|
|
|
||
|
|
if (kType_Is(type, base))
|
||
|
|
{
|
||
|
|
kCheck(kArrayList_Add(types, &type));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kAssembly_FindDerivedTypes(kAssembly assembly, kType base, kArrayList types)
|
||
|
|
{
|
||
|
|
kCheck(kArrayList_Allocate(types, kTypeOf(kType), 0));
|
||
|
|
|
||
|
|
if (!kIsNull(assembly))
|
||
|
|
{
|
||
|
|
return xkAssembly_FindDerivedTypesInAssembly(assembly, base, types);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kArrayList assemblies = kNULL;
|
||
|
|
kSize i;
|
||
|
|
|
||
|
|
kTry
|
||
|
|
{
|
||
|
|
kTest(kArrayList_Construct(&assemblies, kTypeOf(kAssembly), 0, kObject_Alloc(types)));
|
||
|
|
|
||
|
|
kTest(kAssembly_Enumerate(assemblies));
|
||
|
|
|
||
|
|
for (i = 0; i < kArrayList_Count(assemblies); ++i)
|
||
|
|
{
|
||
|
|
kAssembly assembly = kArrayList_AsT(assemblies, i, kAssembly);
|
||
|
|
|
||
|
|
kTest(xkAssembly_FindDerivedTypesInAssembly(assembly, base, types));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
kFinally
|
||
|
|
{
|
||
|
|
kDisposeRef(&assemblies);
|
||
|
|
|
||
|
|
kEndFinally();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|