mirror of https://gitlab.com/nakst/essence
cleanup api
This commit is contained in:
parent
0413a20658
commit
0af72eb18d
|
@ -335,7 +335,7 @@ void FolderEntryCloseHandle(Folder *folder, FolderEntry *entry) {
|
|||
}
|
||||
|
||||
EsHeapFree(entry->name);
|
||||
EsArenaFree(&folder->entryArena, entry);
|
||||
ArenaFree(&folder->entryArena, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,7 @@ FolderEntry *FolderAddEntry(Folder *folder, const char *_name, size_t nameBytes,
|
|||
FolderEntry *entry = (FolderEntry *) HashTableGetLong(&folder->entries, name, nameBytes);
|
||||
|
||||
if (!entry) {
|
||||
entry = (FolderEntry *) EsArenaAllocate(&folder->entryArena, true);
|
||||
entry = (FolderEntry *) ArenaAllocate(&folder->entryArena, true);
|
||||
HashTablePutLong(&folder->entries, name, nameBytes, entry, false);
|
||||
|
||||
static uint64_t nextEntryID = 1;
|
||||
|
@ -566,7 +566,7 @@ void FolderAttachInstance(Instance *instance, String path, bool recurse) {
|
|||
NamespaceFindHandlersForPath(&folder->itemHandler, &folder->containerHandler, path);
|
||||
folder->cEmptyMessage = interfaceString_FileManagerEmptyFolderView;
|
||||
folder->driveRemoved = driveRemoved;
|
||||
EsArenaInitialise(&folder->entryArena, 1048576, sizeof(FolderEntry));
|
||||
ArenaInitialise(&folder->entryArena, 1048576, sizeof(FolderEntry));
|
||||
loadedFolders.Add(folder);
|
||||
|
||||
success:;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <shared/strings.cpp>
|
||||
#include <shared/hash_table.cpp>
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/arena.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/arena.cpp>
|
||||
|
||||
// TODO Possible candidates for moving in the core API:
|
||||
// - String/paths utils
|
||||
|
@ -200,7 +203,7 @@ struct NamespaceHandler {
|
|||
|
||||
struct Folder {
|
||||
HashTable entries;
|
||||
EsArena entryArena;
|
||||
Arena entryArena;
|
||||
|
||||
Array<Instance *> attachedInstances; // NOTE Check Instance::closed is false before accessing the UI!
|
||||
uintptr_t referenceCount;
|
||||
|
|
|
@ -277,19 +277,14 @@ void VariantsPopupCreate(Instance *instance, EsElement *element, EsCommand *) {
|
|||
EsMenuShow(menu);
|
||||
}
|
||||
|
||||
ES_MACRO_SORT(LoadFontsFromDatabaseSort, EsFontInformation, result = EsStringCompare(_left->name, _left->nameBytes, _right->name, _right->nameBytes);, int);
|
||||
|
||||
void LoadFontsFromDatabase(Instance *instance) {
|
||||
EsFontDatabaseEnumerate([] (const EsFontInformation *information, EsGeneric context) {
|
||||
((Instance *) context.p)->fonts.AddPointer(information);
|
||||
}, instance);
|
||||
|
||||
EsSort(instance->fonts.array, instance->fonts.Length(), sizeof(EsFontInformation), [] (const void *left, const void *right, EsGeneric) {
|
||||
EsFontInformation *fontLeft = (EsFontInformation *) left;
|
||||
EsFontInformation *fontRight = (EsFontInformation *) right;
|
||||
int x = EsStringCompare(fontLeft->name, fontLeft->nameBytes, fontRight->name, fontRight->nameBytes);
|
||||
if (x) return x;
|
||||
return EsStringCompareRaw(fontLeft->name, fontLeft->nameBytes, fontRight->name, fontRight->nameBytes);
|
||||
}, 0);
|
||||
|
||||
LoadFontsFromDatabaseSort(instance->fonts.array, instance->fonts.Length(), 0);
|
||||
EsListViewInsert(instance->fontList, 0, 0, instance->fonts.Length());
|
||||
}
|
||||
|
||||
|
|
|
@ -239,6 +239,31 @@ int TextboxDocumentMessage(EsElement *element, EsMessage *message) {
|
|||
}
|
||||
}
|
||||
|
||||
bool StringEndsWith(const char *string, size_t stringBytes, const char *prefix, size_t prefixBytes, bool caseInsensitive) {
|
||||
string += stringBytes - 1;
|
||||
prefix += prefixBytes - 1;
|
||||
|
||||
while (true) {
|
||||
if (!prefixBytes) return true;
|
||||
if (!stringBytes) return false;
|
||||
|
||||
char c1 = *string;
|
||||
char c2 = *prefix;
|
||||
|
||||
if (caseInsensitive) {
|
||||
if (c1 >= 'a' && c1 <= 'z') c1 = c1 - 'a' + 'A';
|
||||
if (c2 >= 'a' && c2 <= 'z') c2 = c2 - 'a' + 'A';
|
||||
}
|
||||
|
||||
if (c1 != c2) return false;
|
||||
|
||||
stringBytes--;
|
||||
prefixBytes--;
|
||||
string--;
|
||||
prefix--;
|
||||
}
|
||||
}
|
||||
|
||||
int InstanceCallback(Instance *instance, EsMessage *message) {
|
||||
if (message->type == ES_MSG_INSTANCE_SAVE) {
|
||||
size_t byteCount;
|
||||
|
@ -260,11 +285,11 @@ int InstanceCallback(Instance *instance, EsMessage *message) {
|
|||
EsTextboxSetSelection(instance->textboxDocument, 0, 0, 0, 0);
|
||||
EsElementRelayout(instance->textboxDocument);
|
||||
|
||||
if (EsStringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".c"), true)
|
||||
|| EsStringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".cpp"), true)
|
||||
|| EsStringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".h"), true)) {
|
||||
if (StringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".c"), true)
|
||||
|| StringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".cpp"), true)
|
||||
|| StringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".h"), true)) {
|
||||
SetLanguage(instance, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C);
|
||||
} else if (EsStringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".ini"), true)) {
|
||||
} else if (StringEndsWith(message->instanceOpen.name, message->instanceOpen.nameBytes, EsLiteral(".ini"), true)) {
|
||||
SetLanguage(instance, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
|
||||
} else {
|
||||
SetLanguage(instance, 0);
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <shared/ini.h>
|
||||
#include <shared/avl_tree.cpp>
|
||||
#include <shared/heap.cpp>
|
||||
#include <shared/arena.cpp>
|
||||
#include <shared/linked_list.cpp>
|
||||
#include <shared/hash.cpp>
|
||||
#include <shared/png_decoder.cpp>
|
||||
|
|
|
@ -1438,7 +1438,7 @@ struct EsListView : EsElement {
|
|||
buffer.position = 0;
|
||||
EsMessageSend(this, &m);
|
||||
|
||||
if (EsStringStartsWith((char *) _buffer, buffer.position, searchBuffer, searchBufferBytes, true)) {
|
||||
if (StringStartsWith((char *) _buffer, buffer.position, searchBuffer, searchBufferBytes, true)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1475,7 +1475,7 @@ struct EsListView : EsElement {
|
|||
m.getContent.group = item->group;
|
||||
buffer.position = 0;
|
||||
EsMessageSend(this, &m);
|
||||
bool shouldShowSearchHighlight = EsStringStartsWith((char *) _buffer, buffer.position, searchBuffer, searchBufferBytes, true);
|
||||
bool shouldShowSearchHighlight = StringStartsWith((char *) _buffer, buffer.position, searchBuffer, searchBufferBytes, true);
|
||||
|
||||
if (shouldShowSearchHighlight || (!shouldShowSearchHighlight && item->showSearchHighlight)) {
|
||||
item->showSearchHighlight = shouldShowSearchHighlight;
|
||||
|
@ -2466,6 +2466,11 @@ void EsListViewRemoveAll(EsListView *view, EsListViewIndex group) {
|
|||
|
||||
int ListViewColumnHeaderItemMessage(EsElement *element, EsMessage *message) {
|
||||
EsListView *view = (EsListView *) element->parent->parent;
|
||||
|
||||
if (message->type == ES_MSG_DESTROY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListViewColumn *column = &view->registeredColumns[element->userData.u];
|
||||
|
||||
if (message->type == ES_MSG_PAINT) {
|
||||
|
@ -2492,6 +2497,11 @@ int ListViewColumnHeaderItemMessage(EsElement *element, EsMessage *message) {
|
|||
|
||||
int ListViewColumnSplitterMessage(EsElement *element, EsMessage *message) {
|
||||
EsListView *view = (EsListView *) element->parent->parent;
|
||||
|
||||
if (message->type == ES_MSG_DESTROY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListViewColumn *column = &view->registeredColumns[element->userData.u];
|
||||
|
||||
if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||
|
|
|
@ -1408,13 +1408,6 @@ struct EsTextSelection {
|
|||
uint32_t foreground, background;
|
||||
};
|
||||
|
||||
struct EsArena {
|
||||
// Arenas are not thread-safe!
|
||||
// You can use different arenas in different threads, though.
|
||||
void *firstEmptySlot, *firstBlock;
|
||||
size_t slotsPerBlock, slotSize, blockSize;
|
||||
};
|
||||
|
||||
struct EsCalculationValue {
|
||||
bool error;
|
||||
double number;
|
||||
|
@ -1976,7 +1969,6 @@ struct EsListViewEnumString {
|
|||
// Function pointer types.
|
||||
|
||||
function_pointer void EsThreadEntryCallback(EsGeneric argument);
|
||||
function_pointer int EsComparisonCallback(const void *left, const void *right, EsGeneric context);
|
||||
function_pointer void EsSwapCallback(const void *left, const void *right, EsGeneric context);
|
||||
function_pointer int EsCRTComparisonCallback(const void *left, const void *right);
|
||||
function_pointer void EsTimerCallback(EsGeneric argument);
|
||||
|
@ -2088,10 +2080,6 @@ function bool EsWorkIsExiting();
|
|||
|
||||
// Memory.
|
||||
|
||||
function void *EsArenaAllocate(EsArena *arena, bool zero); // Not thread-safe.
|
||||
function void EsArenaFree(EsArena *arena, void *pointer); // Not thread-safe.
|
||||
function void EsArenaInitialise(EsArena *arena, size_t blockSize, size_t itemSize);
|
||||
|
||||
function const void *EsBufferRead(EsBuffer *buffer, size_t readBytes);
|
||||
function bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes);
|
||||
function const void *EsBufferReadMany(struct EsBuffer *buffer, size_t a, size_t b);
|
||||
|
@ -2135,9 +2123,6 @@ function void *EsMemoryMapObject(EsHandle object, uintptr_t offset, size_t size,
|
|||
|
||||
function void EsAssertionFailure(EsCString cFile, int line);
|
||||
|
||||
function uint8_t EsRandomU8();
|
||||
function uint64_t EsRandomU64();
|
||||
|
||||
function EsCalculationValue EsCalculateFromUserExpression(EsCString cExpression); // For user input only; do not rely on consistent behaviour across versions; use with message mutex.
|
||||
|
||||
function_not_in_kernel void EsPanic(EsCString format, ...);
|
||||
|
@ -2145,6 +2130,8 @@ function_not_in_kernel void EsPrint(EsCString format, ...);
|
|||
function void EsPrintDirect(STRING string);
|
||||
function void EsPrintHelloWorld();
|
||||
|
||||
function uint8_t EsRandomU8();
|
||||
function uint64_t EsRandomU64();
|
||||
function void EsRandomAddEntropy(uint64_t x);
|
||||
function void EsRandomSeed(uint64_t x);
|
||||
|
||||
|
@ -2163,9 +2150,6 @@ function bool EsRectangleEquals(EsRectangle a, EsRectangle b);
|
|||
function bool EsRectangleContains(EsRectangle a, int32_t x, int32_t y);
|
||||
function bool EsRectangleContainsAll(EsRectangle parent, EsRectangle child); // Returns true iff the child rectangle is entirely contained within parent.
|
||||
|
||||
function void EsSort(void *_base, size_t nmemb, size_t size, EsComparisonCallback compar, EsGeneric argument);
|
||||
function void EsSortWithSwapCallback(void *_base, size_t nmemb, size_t size, EsComparisonCallback compar, EsGeneric argument, EsSwapCallback swap);
|
||||
|
||||
// Graphics.
|
||||
|
||||
function uint32_t EsColorBlend(uint32_t under, uint32_t over, bool fullAlpha);
|
||||
|
@ -2280,7 +2264,6 @@ private function uint64_t DateToLinear(const EsDateComponents *date);
|
|||
|
||||
// Strings.
|
||||
|
||||
function char *EsCStringDuplicate(EsCString string);
|
||||
function size_t EsCStringLength(EsCString string);
|
||||
function char *EsStringAllocateAndFormat(size_t *bytes, EsCString format, ...); // Zero-terminated.
|
||||
function char *EsStringAllocateAndFormatV(size_t *bytes, EsCString format, va_list arguments);
|
||||
|
@ -2291,10 +2274,6 @@ function const char *EsStringFormatTemporary(EsCString format, ...); // Not thr
|
|||
function ptrdiff_t EsStringFormatV(char *buffer, size_t bufferLength, EsCString format, va_list arguments);
|
||||
function bool EsStringFormatAppend(char *buffer, size_t bufferLength, size_t *bufferPosition, EsCString format, ...); // Return false if buffer filled.
|
||||
function bool EsStringFormatAppendV(char *buffer, size_t bufferLength, size_t *bufferPosition, EsCString format, va_list arguments);
|
||||
function size_t EsStringLength(const char *string, uint8_t end);
|
||||
function bool EsStringStartsWith(STRING string, STRING prefix, bool caseInsensitive);
|
||||
function bool EsStringEndsWith(STRING string, STRING prefix, bool caseInsensitive);
|
||||
function char *EsStringZeroTerminate(STRING string); // Free with EsHeapFree.
|
||||
function bool EsUTF8IsValid(const char *input, ptrdiff_t bytes); // Does not check for surrogate characters or overlong sequences of non-ASCII characters.
|
||||
|
||||
function double EsDoubleParse(STRING string, char **endptr);
|
||||
|
|
|
@ -210,6 +210,10 @@ void RastSurfaceFill(RastSurface surface, RastShape shape, RastPaint paint, bool
|
|||
}
|
||||
}
|
||||
|
||||
if (RAST_ARRAY_LENGTH(shape.edges) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RAST_ARRAY(RastEdge) active = { 0 };
|
||||
int edgePosition = 0;
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ extern "C" {
|
|||
#include <shared/avl_tree.cpp>
|
||||
#include <shared/bitset.cpp>
|
||||
#include <shared/range_set.cpp>
|
||||
#include <shared/arena.cpp>
|
||||
|
||||
#include "objects.cpp"
|
||||
#include "memory.cpp"
|
||||
|
@ -206,7 +207,6 @@ extern "C" {
|
|||
#define ARRAY_IMPLEMENTATION_ONLY
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/heap.cpp>
|
||||
#include <shared/arena.cpp>
|
||||
#include <shared/partitions.cpp>
|
||||
#include <shared/ini.h>
|
||||
#endif
|
||||
|
|
|
@ -413,7 +413,7 @@ struct Networking {
|
|||
NetTask *echoRequestTask;
|
||||
|
||||
KMutex transmitBufferPoolMutex;
|
||||
EsArena transmitBufferPool;
|
||||
Arena transmitBufferPool;
|
||||
};
|
||||
|
||||
struct NetDomainNameResolveTask : NetTask {
|
||||
|
@ -499,7 +499,7 @@ void NetPrintPacket(const char *cName, const void *packet, size_t bytes) {
|
|||
EsBuffer NetTransmitBufferGet() {
|
||||
KMutexAcquire(&networking.transmitBufferPoolMutex);
|
||||
EsBuffer buffer = {};
|
||||
buffer.out = (uint8_t *) EsArenaAllocate(&networking.transmitBufferPool, false);
|
||||
buffer.out = (uint8_t *) ArenaAllocate(&networking.transmitBufferPool, false);
|
||||
buffer.bytes = networking.transmitBufferPool.slotSize;
|
||||
|
||||
if (!buffer.out) {
|
||||
|
@ -513,7 +513,7 @@ EsBuffer NetTransmitBufferGet() {
|
|||
|
||||
void NetTransmitBufferReturn(void *data) {
|
||||
KMutexAcquire(&networking.transmitBufferPoolMutex);
|
||||
EsArenaFree(&networking.transmitBufferPool, data);
|
||||
ArenaFree(&networking.transmitBufferPool, data);
|
||||
KMutexRelease(&networking.transmitBufferPoolMutex);
|
||||
}
|
||||
|
||||
|
@ -2155,7 +2155,7 @@ void KRegisterNetInterface(NetInterface *interface) {
|
|||
void NetInitialise(KDevice *) {
|
||||
networking.udpTaskBitset.Initialise(MAX_UDP_TASKS);
|
||||
networking.udpTaskBitset.PutAll();
|
||||
EsArenaInitialise(&networking.transmitBufferPool, 1048576, 2048);
|
||||
ArenaInitialise(&networking.transmitBufferPool, 1048576, 2048);
|
||||
|
||||
networking.tcpTaskLRU = networking.tcpTaskMRU = 0xFFFF;
|
||||
|
||||
|
|
|
@ -2,19 +2,34 @@
|
|||
// It is released under the terms of the MIT license -- see LICENSE.md.
|
||||
// Written by: nakst.
|
||||
|
||||
#ifndef IMPLEMENTATION
|
||||
|
||||
struct Arena {
|
||||
// Arenas are not thread-safe!
|
||||
// You can use different arenas in different threads, though.
|
||||
void *firstEmptySlot, *firstBlock;
|
||||
size_t slotsPerBlock, slotSize, blockSize;
|
||||
};
|
||||
|
||||
void *ArenaAllocate(Arena *arena, bool zero); // Not thread-safe.
|
||||
void ArenaFree(Arena *arena, void *pointer); // Not thread-safe.
|
||||
void ArenaInitialise(Arena *arena, size_t blockSize, size_t itemSize);
|
||||
|
||||
#else
|
||||
|
||||
struct ArenaSlot {
|
||||
uintptr_t indexInBlock;
|
||||
ArenaSlot *nextEmpty, **previousEmpty;
|
||||
};
|
||||
|
||||
struct ArenaBlock {
|
||||
struct EsArena *arena;
|
||||
struct Arena *arena;
|
||||
size_t usedSlots;
|
||||
uint8_t *data;
|
||||
ArenaBlock *nextBlock;
|
||||
};
|
||||
|
||||
void EsArenaFree(EsArena *arena, void *pointer) {
|
||||
void ArenaFree(Arena *arena, void *pointer) {
|
||||
if (!pointer) return;
|
||||
|
||||
ArenaBlock **blockReference = (ArenaBlock **) &arena->firstBlock;
|
||||
|
@ -60,7 +75,7 @@ void EsArenaFree(EsArena *arena, void *pointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void *EsArenaAllocate(EsArena *arena, bool zero) {
|
||||
void *ArenaAllocate(Arena *arena, bool zero) {
|
||||
if (!arena->firstEmptySlot) {
|
||||
#ifdef KERNEL
|
||||
ArenaBlock *block = (ArenaBlock *) EsHeapAllocate(arena->slotsPerBlock * sizeof(ArenaSlot) + sizeof(ArenaBlock), false, K_FIXED);
|
||||
|
@ -98,10 +113,12 @@ void *EsArenaAllocate(EsArena *arena, bool zero) {
|
|||
return pointer;
|
||||
}
|
||||
|
||||
void EsArenaInitialise(EsArena *arena, size_t blockSize, size_t itemSize) {
|
||||
void ArenaInitialise(Arena *arena, size_t blockSize, size_t itemSize) {
|
||||
EsAssert(!arena->slotSize && itemSize);
|
||||
arena->slotSize = itemSize;
|
||||
arena->slotsPerBlock = blockSize / arena->slotSize;
|
||||
if (arena->slotsPerBlock < 32) arena->slotsPerBlock = 32;
|
||||
arena->blockSize = arena->slotsPerBlock * arena->slotSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,24 +27,35 @@ template <class T, EsHeap *heap = nullptr>
|
|||
struct Array {
|
||||
T *array;
|
||||
|
||||
__attribute__((no_instrument_function)) inline size_t Length() { return array ? ArrayHeader(array)->length : 0; }
|
||||
inline T &First() { return array[0]; }
|
||||
inline T &Last() { return array[Length() - 1]; }
|
||||
inline void Delete(uintptr_t position) { _ArrayDelete(array, position, sizeof(T), 1); }
|
||||
inline void DeleteSwap(uintptr_t position) { _ArrayDeleteSwap(array, position, sizeof(T)); }
|
||||
inline void DeleteMany(uintptr_t position, size_t count) { _ArrayDelete(array, position, sizeof(T), count); }
|
||||
inline T *Add(T item) { return (T *) _ArrayInsert((void **) &array, &item, sizeof(T), -1, 0, heap); }
|
||||
inline T *Add() { return (T *) _ArrayInsert((void **) &array, nullptr, sizeof(T), -1, 0, heap); }
|
||||
inline T *Insert(T item, uintptr_t position) { return (T *) _ArrayInsert((void **) &array, &item, sizeof(T), position, 0, heap); }
|
||||
inline T *AddPointer(const T *item) { return (T *) _ArrayInsert((void **) &(array), item, sizeof(T), -1, 0, heap); }
|
||||
inline T *InsertPointer(const T *item, uintptr_t position) { return (T *) _ArrayInsert((void **) &array, item, sizeof(T), position, 0, heap); }
|
||||
inline T *InsertMany(uintptr_t position, size_t count) { return (T *) _ArrayInsertMany((void **) &array, sizeof(T), position, count, heap); }
|
||||
inline bool SetLength(size_t length) { return _ArraySetLength((void **) &array, length, sizeof(T), 0, heap); }
|
||||
inline void Free() { _ArrayFree((void **) &array, sizeof(T), heap); }
|
||||
inline T Pop() { T t = Last(); Delete(Length() - 1); return t; }
|
||||
inline T &operator[](uintptr_t index) { return array[index]; }
|
||||
T &First() { return array[0]; }
|
||||
T &Last() { return array[Length() - 1]; }
|
||||
void Delete(uintptr_t position) { _ArrayDelete(array, position, sizeof(T), 1); }
|
||||
void DeleteSwap(uintptr_t position) { _ArrayDeleteSwap(array, position, sizeof(T)); }
|
||||
void DeleteMany(uintptr_t position, size_t count) { _ArrayDelete(array, position, sizeof(T), count); }
|
||||
T *Add(T item) { return (T *) _ArrayInsert((void **) &array, &item, sizeof(T), -1, 0, heap); }
|
||||
T *Add() { return (T *) _ArrayInsert((void **) &array, nullptr, sizeof(T), -1, 0, heap); }
|
||||
T *Insert(T item, uintptr_t position) { return (T *) _ArrayInsert((void **) &array, &item, sizeof(T), position, 0, heap); }
|
||||
T *AddPointer(const T *item) { return (T *) _ArrayInsert((void **) &(array), item, sizeof(T), -1, 0, heap); }
|
||||
T *InsertPointer(const T *item, uintptr_t position) { return (T *) _ArrayInsert((void **) &array, item, sizeof(T), position, 0, heap); }
|
||||
T *InsertMany(uintptr_t position, size_t count) { return (T *) _ArrayInsertMany((void **) &array, sizeof(T), position, count, heap); }
|
||||
bool SetLength(size_t length) { return _ArraySetLength((void **) &array, length, sizeof(T), 0, heap); }
|
||||
void Free() { _ArrayFree((void **) &array, sizeof(T), heap); }
|
||||
T Pop() { T t = Last(); Delete(Length() - 1); return t; }
|
||||
|
||||
inline intptr_t Find(T item, bool failIfNotFound) {
|
||||
__attribute__((no_instrument_function))
|
||||
size_t Length() {
|
||||
return array ? ArrayHeader(array)->length : 0;
|
||||
}
|
||||
|
||||
__attribute__((no_instrument_function))
|
||||
T &operator[](uintptr_t index) {
|
||||
#ifdef DEBUG_BUILD
|
||||
EsAssert(index < Length());
|
||||
#endif
|
||||
return array[index];
|
||||
}
|
||||
|
||||
intptr_t Find(T item, bool failIfNotFound) {
|
||||
for (uintptr_t i = 0; i < Length(); i++) {
|
||||
if (array[i] == item) {
|
||||
return i;
|
||||
|
@ -55,21 +66,21 @@ struct Array {
|
|||
return -1;
|
||||
}
|
||||
|
||||
inline bool FindAndDelete(T item, bool failIfNotFound) {
|
||||
bool FindAndDelete(T item, bool failIfNotFound) {
|
||||
intptr_t index = Find(item, failIfNotFound);
|
||||
if (index == -1) return false;
|
||||
Delete(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool FindAndDeleteSwap(T item, bool failIfNotFound) {
|
||||
bool FindAndDeleteSwap(T item, bool failIfNotFound) {
|
||||
intptr_t index = Find(item, failIfNotFound);
|
||||
if (index == -1) return false;
|
||||
DeleteSwap(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void AddFast(T item) {
|
||||
void AddFast(T item) {
|
||||
if (!array) { Add(item); return; }
|
||||
_ArrayHeader *header = ArrayHeader(array);
|
||||
if (header->length == header->allocated) { Add(item); return; }
|
||||
|
|
|
@ -475,23 +475,6 @@ size_t EsCStringLength(const char *string) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t EsStringLength(const char *string, uint8_t end) {
|
||||
if (!string) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t size = 0;
|
||||
|
||||
while (true) {
|
||||
if (*string != end) {
|
||||
size++;
|
||||
string++;
|
||||
} else {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*FormatCallback)(int character, void *data);
|
||||
|
||||
void _FormatInteger(FormatCallback callback, void *callbackData, long value, int pad = 0, bool simple = false) {
|
||||
|
@ -841,24 +824,6 @@ void EsBufferFormatV(EsBuffer *buffer, EsCString format, va_list arguments) {
|
|||
}
|
||||
|
||||
#ifndef KERNEL
|
||||
char *EsCStringDuplicate(const char *string) {
|
||||
size_t length = EsCStringLength(string);
|
||||
char *buffer = (char *) EsHeapAllocate(length + 1, false);
|
||||
if (!buffer) return nullptr;
|
||||
EsMemoryCopy(buffer, string, length);
|
||||
buffer[length] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *EsStringZeroTerminate(const char *string, ptrdiff_t stringBytes) {
|
||||
if (stringBytes == -1) stringBytes = EsCStringLength(string);
|
||||
char *result = (char *) EsHeapAllocate(stringBytes + 1, false);
|
||||
if (!result) return nullptr;
|
||||
result[stringBytes] = 0;
|
||||
EsMemoryCopy(result, string, stringBytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
char *EsStringAllocateAndFormatV(size_t *bytes, const char *format, va_list arguments1) {
|
||||
size_t needed = 0;
|
||||
|
||||
|
@ -1021,7 +986,7 @@ int EsStringCompare(const char *s1, ptrdiff_t _length1, const char *s2, ptrdiff_
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool EsStringStartsWith(const char *string, intptr_t _stringBytes, const char *prefix, intptr_t _prefixBytes, bool caseInsensitive) {
|
||||
bool StringStartsWith(const char *string, intptr_t _stringBytes, const char *prefix, intptr_t _prefixBytes, bool caseInsensitive) {
|
||||
if (_stringBytes == -1) _stringBytes = EsCStringLength(string);
|
||||
if (_prefixBytes == -1) _prefixBytes = EsCStringLength(prefix);
|
||||
size_t stringBytes = _stringBytes, prefixBytes = _prefixBytes;
|
||||
|
@ -1047,34 +1012,6 @@ bool EsStringStartsWith(const char *string, intptr_t _stringBytes, const char *p
|
|||
}
|
||||
}
|
||||
|
||||
bool EsStringEndsWith(const char *string, intptr_t _stringBytes, const char *prefix, intptr_t _prefixBytes, bool caseInsensitive) {
|
||||
if (_stringBytes == -1) _stringBytes = EsCStringLength(string);
|
||||
if (_prefixBytes == -1) _prefixBytes = EsCStringLength(prefix);
|
||||
size_t stringBytes = _stringBytes, prefixBytes = _prefixBytes;
|
||||
string += stringBytes - 1;
|
||||
prefix += prefixBytes - 1;
|
||||
|
||||
while (true) {
|
||||
if (!prefixBytes) return true;
|
||||
if (!stringBytes) return false;
|
||||
|
||||
char c1 = *string;
|
||||
char c2 = *prefix;
|
||||
|
||||
if (caseInsensitive) {
|
||||
if (c1 >= 'a' && c1 <= 'z') c1 = c1 - 'a' + 'A';
|
||||
if (c2 >= 'a' && c2 <= 'z') c2 = c2 - 'a' + 'A';
|
||||
}
|
||||
|
||||
if (c1 != c2) return false;
|
||||
|
||||
stringBytes--;
|
||||
prefixBytes--;
|
||||
string--;
|
||||
prefix--;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EsColorParse(const char *string, ptrdiff_t bytes) {
|
||||
if (bytes == -1) {
|
||||
bytes = EsCStringLength(string);
|
||||
|
|
|
@ -70,9 +70,6 @@ EsThreadCreate=68
|
|||
EsThreadGetID=69
|
||||
EsCRTstrdup=70
|
||||
EsThreadTerminate=71
|
||||
EsArenaAllocate=72
|
||||
EsArenaFree=73
|
||||
EsArenaInitialise=74
|
||||
EsConstantBufferCreate=75
|
||||
EsConstantBufferRead=76
|
||||
EsConstantBufferShare=77
|
||||
|
@ -107,8 +104,6 @@ EsElementGetMetrics=105
|
|||
EsRandomAddEntropy=106
|
||||
EsRandomSeed=107
|
||||
EsInstanceSetClassEditor=108
|
||||
EsSort=109
|
||||
EsSortWithSwapCallback=110
|
||||
EsColorBlend=111
|
||||
EsColorConvertToRGB=112
|
||||
EsColorConvertToHSV=113
|
||||
|
@ -161,11 +156,8 @@ EsStringFormatTemporary=159
|
|||
EsStringFormatV=160
|
||||
EsStringFormatAppend=161
|
||||
EsStringFormatAppendV=162
|
||||
EsStringLength=163
|
||||
EsSystemConfigurationReadFileTypes=164
|
||||
EsImageLoad=165
|
||||
EsStringStartsWith=166
|
||||
EsStringZeroTerminate=167
|
||||
EsCRTabs=168
|
||||
EsCRTacosf=169
|
||||
EsCRTasinf=170
|
||||
|
@ -340,12 +332,10 @@ EsClipboardReadText=338
|
|||
EsClipboardOpen=339
|
||||
EsSpacerCreate=340
|
||||
EsTextPlanCreate=341
|
||||
EsStringEndsWith=342
|
||||
EsListDisplayCreate=343
|
||||
EsCRTfabsf=344
|
||||
EsCRTisnanf=345
|
||||
EsListDisplaySetCounterContinuation=346
|
||||
EsCStringDuplicate=347
|
||||
EsImageDisplayLoadBits=348
|
||||
EsImageDisplayLoadFromMemory=349
|
||||
EsTextDisplaySetupSyntaxHighlighting=350
|
||||
|
|
Loading…
Reference in New Issue