[DEV] add an allocator checker
This commit is contained in:
parent
2a02c0c0be
commit
49f30a03e0
@ -11,6 +11,7 @@
|
||||
#include <echrono/Steady.hpp>
|
||||
#include <echrono/Duration.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <etk/Allocator.hpp>
|
||||
|
||||
static int32_t nbTimeInit = 0;
|
||||
|
||||
@ -207,19 +208,31 @@ int32_t etest::runAllTest() {
|
||||
if (it->getTestGroup() != itGroup) {
|
||||
continue;
|
||||
}
|
||||
ETEST_PRINT("[ RUN ] " << itGroup << "." << it->getTestName());
|
||||
it->clearLocal();
|
||||
g_currentTest = it;
|
||||
echrono::Steady ticTest = echrono::Steady::now();
|
||||
it->run();
|
||||
echrono::Steady tocTest = echrono::Steady::now();
|
||||
g_currentTest = nullptr;
|
||||
if (it->getError() == true) {
|
||||
ETEST_PRINT("[ FAIL ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
||||
errorCount++;
|
||||
} else {
|
||||
ETEST_PRINT("[ OK ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
||||
#if ETK_MEMORY_CHECKER >= 0
|
||||
uint64_t* memorySnapShoot = etk::memory::createSnapshoot();
|
||||
#endif
|
||||
{
|
||||
ETEST_PRINT("[ RUN ] " << itGroup << "." << it->getTestName());
|
||||
it->clearLocal();
|
||||
g_currentTest = it;
|
||||
echrono::Steady ticTest = echrono::Steady::now();
|
||||
it->run();
|
||||
echrono::Steady tocTest = echrono::Steady::now();
|
||||
g_currentTest = nullptr;
|
||||
if (it->getError() == true) {
|
||||
ETEST_PRINT("[ FAIL ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
||||
errorCount++;
|
||||
} else {
|
||||
ETEST_PRINT("[ OK ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
||||
}
|
||||
}
|
||||
#if ETK_MEMORY_CHECKER >= 0
|
||||
ETEST_DEBUG("[ MEM ] CHECK memory properties");
|
||||
bool ret = etk::memory::checkSnapshoot(memorySnapShoot);
|
||||
etk::memory::clearSnapshoot(memorySnapShoot);
|
||||
memorySnapShoot = nullptr;
|
||||
ETEST_DEBUG("[ MEM ] CHECK memory properties (done)");
|
||||
#endif
|
||||
}
|
||||
echrono::Steady tocGroup = echrono::Steady::now();
|
||||
ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << " (" << (tocGroup - ticGroup) << ")");
|
||||
@ -229,6 +242,7 @@ int32_t etest::runAllTest() {
|
||||
if (errorCount != 0) {
|
||||
ETEST_PRINT("[== FAIL ==] Have " << errorCount << " test fail");
|
||||
}
|
||||
ETK_MEM_SHOW_LOG();
|
||||
return -errorCount;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,8 @@ namespace etest {
|
||||
void run() override; \
|
||||
}; \
|
||||
\
|
||||
uint32_t TEST_CLASS_NAME(groupName, localName)::registerElement = etest::registerTest(new TEST_CLASS_NAME(groupName, localName)); \
|
||||
uint32_t TEST_CLASS_NAME(groupName, localName)::registerElement = etest::registerTest(\
|
||||
etk::memory::allocatorNewFull<TEST_CLASS_NAME(groupName, localName)>("etest_test_class", nullptr, __LINE__, __FILE__)); \
|
||||
\
|
||||
void TEST_CLASS_NAME(groupName, localName)::run()
|
||||
|
||||
|
@ -26,3 +26,721 @@ void operator delete[] (void* ptr) {
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if ETK_MEMORY_CHECKER > 0
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
|
||||
#define ETK_MEM_DEBUG_LEVEL 4
|
||||
|
||||
#define ETK_MEMORY_PRINT(...) \
|
||||
do { \
|
||||
printf("[PRINT] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
|
||||
#if ETK_MEM_DEBUG_LEVEL > 0
|
||||
#define ETK_MEMORY_ERROR(...) \
|
||||
do { \
|
||||
printf("[ERROR] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ETK_MEMORY_ERROR(...) do {} while (false)
|
||||
#endif
|
||||
#if ETK_MEM_DEBUG_LEVEL > 1
|
||||
#define ETK_MEMORY_WARNING(...) \
|
||||
do { \
|
||||
printf("[WARNING] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ETK_MEMORY_WARNING(...) do {} while (false)
|
||||
#endif
|
||||
#if ETK_MEM_DEBUG_LEVEL > 2
|
||||
#define ETK_MEMORY_INFO(...) \
|
||||
do { \
|
||||
printf("[INFO] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ETK_MEMORY_INFO(...) do {} while (false)
|
||||
#endif
|
||||
#if ETK_MEM_DEBUG_LEVEL > 3
|
||||
#define ETK_MEMORY_DEBUG(...) \
|
||||
do { \
|
||||
printf("[DEBUG] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ETK_MEMORY_DEBUG(...) do {} while (false)
|
||||
#endif
|
||||
|
||||
#if ETK_MEM_DEBUG_LEVEL > 4
|
||||
#define ETK_MEMORY_VERBOSE(...) \
|
||||
do { \
|
||||
printf("[VERBOSE] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ETK_MEMORY_VERBOSE(...) do {} while (false)
|
||||
#endif
|
||||
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
// Max stric size of filename, variable Name, and fonction Name
|
||||
#define ETK_MEM_MAX_STRING_SIZE (77)
|
||||
#endif
|
||||
/**
|
||||
* @brief Class to save allocation elements
|
||||
*/
|
||||
class MemoryElementSystem {
|
||||
public:
|
||||
bool used; //!< for list system
|
||||
char* pointerAllocated; //!< pointer really allocated
|
||||
char* pointerGiveToUser; //!< pointer sent to the USER (in case of check of memory overflow)
|
||||
size_t sizeUser; //!< User request size
|
||||
size_t sizeAllocate; //!< data size really allocated by the tool
|
||||
size_t sizeData; //!< current data size of allocated memory
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
size_t id; //!< Element ID to know the allocation Order
|
||||
char variableName[ETK_MEM_MAX_STRING_SIZE]; //!< Variable name when allocate
|
||||
char functionName[ETK_MEM_MAX_STRING_SIZE]; //!< function name that allocate this buffer
|
||||
char fileName[ETK_MEM_MAX_STRING_SIZE]; //!< function name that allocate this buffer
|
||||
size_t functionLine; //!< function line where the buffer was allocated
|
||||
#endif
|
||||
};
|
||||
|
||||
class memoryAllocatorHandle {
|
||||
private:
|
||||
// to prevent double access:
|
||||
pthread_mutex_t m_mutex;
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
// Basic header to check the memory everflow (abstract element)
|
||||
uint8_t* m_blockCheckMemory;
|
||||
// To know the size of pre header and Post-header
|
||||
uint32_t m_checkBorneSize;
|
||||
#endif
|
||||
// To do statictic memory allocation (Total of memory allocate from the start of program)
|
||||
uint64_t m_totalMemAllocated;
|
||||
// To do statictic memory allocation (Current size of allocated memory)
|
||||
uint64_t m_currentMemAllocated;
|
||||
// To do statictic memory allocation (Current size of allocated memory)
|
||||
int64_t m_currentMemAllocatedCount;
|
||||
int64_t m_currentMemAllocatedCountSize[64];
|
||||
int64_t m_totalMemAllocatedCountSize[64];
|
||||
// To do statictic memory allocation (Max of memory allocated in the same Time)
|
||||
uint64_t m_maxMemoryAllocated;
|
||||
// To do statictic memory allocation (number of allocation)
|
||||
int64_t m_dynamicID;
|
||||
// To know if this memory system is initialized
|
||||
bool m_memSystemInitialize;
|
||||
// List of element to remember allocate...
|
||||
size_t m_memListElementSize;
|
||||
MemoryElementSystem* m_memListElements;
|
||||
public:
|
||||
memoryAllocatorHandle():
|
||||
m_mutex(PTHREAD_MUTEX_INITIALIZER),
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
// Basic header to check the memory everflow (abstract element)
|
||||
m_blockCheckMemory(nullptr),
|
||||
m_checkBorneSize(10*8),
|
||||
#endif
|
||||
m_totalMemAllocated(0),
|
||||
m_currentMemAllocated(0),
|
||||
m_currentMemAllocatedCount(0),
|
||||
m_maxMemoryAllocated(0),
|
||||
m_dynamicID(0),
|
||||
m_memSystemInitialize(false),
|
||||
m_memListElementSize(1024),
|
||||
m_memListElements(nullptr) {
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
static const uint8_t blockCheckMemory[] = {
|
||||
0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
|
||||
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
||||
};
|
||||
m_blockCheckMemory = (uint8_t*)blockCheckMemory;
|
||||
#endif
|
||||
lock();
|
||||
memset(m_totalMemAllocatedCountSize, 0, sizeof(m_totalMemAllocatedCountSize));
|
||||
memset(m_currentMemAllocatedCountSize, 0, sizeof(m_currentMemAllocatedCountSize));
|
||||
if (m_memSystemInitialize == true) {
|
||||
return;
|
||||
}
|
||||
int systemRet;
|
||||
if (m_memListElements == nullptr) {
|
||||
m_memListElements = new MemoryElementSystem[m_memListElementSize];
|
||||
}
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
m_memListElements[iii].used = false;
|
||||
}
|
||||
m_memSystemInitialize = true;
|
||||
unLock();
|
||||
}
|
||||
/**
|
||||
* @brief Update statistique
|
||||
* @param[in] _dataSize Allocated size
|
||||
*/
|
||||
void addMemory(size_t _dataSize) {
|
||||
m_totalMemAllocated += _dataSize;
|
||||
m_currentMemAllocated += _dataSize;
|
||||
if (m_currentMemAllocated > m_maxMemoryAllocated) {
|
||||
m_maxMemoryAllocated = m_currentMemAllocated;
|
||||
}
|
||||
m_currentMemAllocatedCount++;
|
||||
for (int32_t iii=0; iii<64; ++iii) {
|
||||
if (_dataSize <= (uint64_t(1) << iii)) {
|
||||
m_totalMemAllocatedCountSize[iii]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int32_t iii=0; iii<64; ++iii) {
|
||||
if (_dataSize <= (uint64_t(1) << iii)) {
|
||||
m_currentMemAllocatedCountSize[iii]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void lock() {
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
void unLock() {
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
/**
|
||||
* @brief Update memory statistique
|
||||
* @param[in] dataSize Removed size.
|
||||
*/
|
||||
void removeMemory(size_t _dataSize) {
|
||||
m_currentMemAllocated -= _dataSize;
|
||||
m_currentMemAllocatedCount--;
|
||||
for (int32_t iii=0; iii<64; ++iii) {
|
||||
if (_dataSize <= (uint64_t(1) << iii)) {
|
||||
m_currentMemAllocatedCountSize[iii]--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a current free element of the structure
|
||||
* @return the free Element find or nullptr
|
||||
*/
|
||||
MemoryElementSystem* getFreeElement() {
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == false) {
|
||||
return &(m_memListElements[iii]);
|
||||
}
|
||||
}
|
||||
// resize Linker size:
|
||||
m_memListElementSize *= 2;
|
||||
ETK_MEMORY_DEBUG("Realloate the allocator memory system: %ld", uint64_t(m_memListElementSize));
|
||||
MemoryElementSystem* tmp = new MemoryElementSystem[m_memListElementSize];
|
||||
if (tmp == nullptr) {
|
||||
m_memListElementSize /= 2;
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
tmp[iii].used = false;
|
||||
}
|
||||
memcpy(tmp, m_memListElements, sizeof(MemoryElementSystem) * m_memListElementSize / 2);
|
||||
delete[] m_memListElements;
|
||||
m_memListElements = tmp;
|
||||
// try again
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == false) {
|
||||
return &(m_memListElements[iii]);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief Get the element structure reference if it existed
|
||||
* @param[in] pointerAdresse pointer to retreave the element
|
||||
* @return get the element reference for the curent adress pointer
|
||||
*/
|
||||
MemoryElementSystem *getAdressedElement(char* _pointerAdresse) {
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
if (m_memListElements[iii].pointerGiveToUser == _pointerAdresse) {
|
||||
return &(m_memListElements[iii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
/**
|
||||
* @brief Verify the curent Memory header
|
||||
* This function vereify the memeory with the common header and header size.
|
||||
* @param[in] pointerAdresse Start pointer to verify data
|
||||
* @return the check result :
|
||||
* - true : if an error existe
|
||||
* - false : if no error
|
||||
*/
|
||||
bool checkMem(char* _pointerAdresse) {
|
||||
uint8_t *pointer = (uint8_t*)_pointerAdresse;
|
||||
for (size_t iii=0; iii<m_checkBorneSize; ++iii) {
|
||||
if (*(pointer++) != m_blockCheckMemory[iii]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
/**
|
||||
* @brief Display the current buffer to check error.
|
||||
* Desactivated by debault (only for extreme debug)
|
||||
* @param[in] _pointerAdresse pointer to start the print
|
||||
* @param[in] _size number of char to display
|
||||
*/
|
||||
void displayBuffer(char* _pointerAdresse, uint32_t _size) {
|
||||
/*
|
||||
uint8_t *pointer = (uint8_t *)_pointerAdresse;
|
||||
uint32_t i;
|
||||
for (i=0; i<_size ;i++) {
|
||||
if (i%50 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("%02X ", pointer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
/**
|
||||
* @brief Get the filename (without all the Path)
|
||||
* @param[in] _fileLink pointer on the name with the Path
|
||||
* @return The last pointer of the filename
|
||||
*/
|
||||
const char *getFileName(const char* _fileLink) {
|
||||
const char *element_2 = _fileLink;
|
||||
const char *element_1 = _fileLink;
|
||||
const char *element_0 = _fileLink;
|
||||
const char * pch = nullptr;
|
||||
pch = _fileLink;
|
||||
while (pch != nullptr) {
|
||||
element_2 = element_1;
|
||||
element_1 = element_0;
|
||||
element_0 = pch;
|
||||
pch = strchr(pch+1, '/');
|
||||
}
|
||||
return element_2;
|
||||
}
|
||||
#endif
|
||||
void displayMemoryProperty(MemoryElementSystem& _element) {
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
bool errorOccured = false;
|
||||
ETK_MEMORY_WARNING("Not FREE : %p ==> %p : %ld Bytes var=%s",
|
||||
_element.pointerAllocated,
|
||||
_element.pointerGiveToUser,
|
||||
_element.sizeUser,
|
||||
_element.variableName);
|
||||
ETK_MEMORY_WARNING("%8d : %s() line=%ld file=%s",
|
||||
(uint32_t)_element.id,
|
||||
_element.functionName,
|
||||
_element.functionLine,
|
||||
_element.fileName);
|
||||
if (checkMem(_element.pointerAllocated) == true) {
|
||||
ETK_MEMORY_ERROR("MEM LOG (L): %s : %ld Bytes @ %p ==> user @ %p (depassement pre)",
|
||||
_element.variableName,
|
||||
_element.sizeUser,
|
||||
_element.pointerAllocated,
|
||||
_element.pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (checkMem(_element.pointerAllocated + _element.sizeUser + m_checkBorneSize) == true) {
|
||||
ETK_MEMORY_ERROR("MEM LOG (L): %s : %ld Bytes @ %p ==> user @ %p (depassement post)",
|
||||
_element.variableName,
|
||||
_element.sizeUser,
|
||||
_element.pointerAllocated,
|
||||
_element.pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (errorOccured == true) {
|
||||
displayBuffer(_element.pointerAllocated,
|
||||
_element.sizeAllocate);
|
||||
assert(false);
|
||||
}
|
||||
#else
|
||||
ETK_MEMORY_WARNING("Not LOG : %p ==> %p : %d Bytes",
|
||||
_element.pointerAllocated,
|
||||
_element.pointerGiveToUser,
|
||||
_element.sizeUser);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t* createSnapshoot() {
|
||||
lock();
|
||||
size_t countElement = 0;
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
countElement++;
|
||||
}
|
||||
}
|
||||
if (countElement == 0) {
|
||||
unLock();
|
||||
return nullptr;
|
||||
}
|
||||
ETK_MEMORY_VERBOSE("find %ld element in memory", (uint64_t)countElement);
|
||||
uint64_t* out = new uint64_t[countElement+10];
|
||||
memset(out, 0, sizeof(uint64_t)*(countElement+10));
|
||||
countElement = 0;
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
out[countElement++] = uint64_t(m_memListElements[iii].pointerAllocated);
|
||||
}
|
||||
}
|
||||
unLock();
|
||||
return out;
|
||||
}
|
||||
|
||||
bool checkSnapshoot(uint64_t* _handle) {
|
||||
if (_handle == nullptr) {
|
||||
return false;
|
||||
}
|
||||
lock();
|
||||
bool haveError = false;
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
uint64_t* dataBase = _handle;
|
||||
bool find = false;
|
||||
size_t jjj = 0;
|
||||
while (dataBase[jjj] != 0) {
|
||||
if (dataBase[jjj] == uint64_t(m_memListElements[iii].pointerAllocated)) {
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
jjj++;
|
||||
//dataBase++;
|
||||
}
|
||||
if (find == false) {
|
||||
haveError = true;
|
||||
displayMemoryProperty(m_memListElements[iii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
unLock();
|
||||
return haveError == false;
|
||||
}
|
||||
|
||||
void clearSnapshoot(uint64_t* _handle) {
|
||||
if (_handle == nullptr) {
|
||||
return;
|
||||
}
|
||||
delete[] (uint64_t*)_handle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* allocate(size_t _num,
|
||||
size_t _size,
|
||||
const char* _variableName,
|
||||
const char* _functionName,
|
||||
int32_t _line,
|
||||
const char* _fileName) {
|
||||
MemoryElementSystem* myElement;
|
||||
lock();
|
||||
m_dynamicID++;
|
||||
myElement = getFreeElement();
|
||||
// check free handle
|
||||
if (myElement != nullptr) {
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
const char *fileNameShort = nullptr;
|
||||
myElement->id = m_dynamicID;
|
||||
#endif
|
||||
// if an element is free :
|
||||
myElement->sizeUser = _size * _num;
|
||||
myElement->sizeData = _size;
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
myElement->sizeAllocate = myElement->sizeUser + m_checkBorneSize*2;
|
||||
if (_variableName == nullptr) {
|
||||
strncpy(myElement->variableName, "---", ETK_MEM_MAX_STRING_SIZE);
|
||||
} else {
|
||||
strncpy(myElement->variableName, _variableName, ETK_MEM_MAX_STRING_SIZE);
|
||||
}
|
||||
myElement->variableName[ETK_MEM_MAX_STRING_SIZE-1] = 0;
|
||||
if (_functionName == nullptr) {
|
||||
strncpy(myElement->functionName, "---", ETK_MEM_MAX_STRING_SIZE);
|
||||
} else {
|
||||
strncpy(myElement->functionName, _functionName, ETK_MEM_MAX_STRING_SIZE);
|
||||
}
|
||||
myElement->functionName[ETK_MEM_MAX_STRING_SIZE-1] = 0;
|
||||
if (_fileName == nullptr) {
|
||||
strncpy(myElement->fileName, "---", ETK_MEM_MAX_STRING_SIZE);
|
||||
} else {
|
||||
fileNameShort = getFileName(_fileName);
|
||||
strncpy(myElement->fileName, fileNameShort, ETK_MEM_MAX_STRING_SIZE);
|
||||
}
|
||||
myElement->fileName[ETK_MEM_MAX_STRING_SIZE-1] = 0;
|
||||
myElement->functionLine = _line;
|
||||
#else
|
||||
myElement->sizeAllocate = myElement->sizeUser;
|
||||
#endif
|
||||
myElement->pointerAllocated = nullptr;
|
||||
myElement->pointerGiveToUser = nullptr;
|
||||
// real allocation :
|
||||
myElement->pointerAllocated = new char[myElement->sizeAllocate];
|
||||
if (myElement->pointerAllocated != nullptr) {
|
||||
// set edded memory
|
||||
addMemory(myElement->sizeUser);
|
||||
// save curent pointer
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
myElement->pointerGiveToUser = myElement->pointerAllocated + m_checkBorneSize;
|
||||
#else
|
||||
myElement->pointerGiveToUser = myElement->pointerAllocated;
|
||||
#endif
|
||||
ETK_MEMORY_VERBOSE("MEM allocate (L): %s : %ld Bytes @ %p ==> user @ %p", _variableName, _num*_size, myElement->pointerAllocated, myElement->pointerGiveToUser);
|
||||
// set bornes:
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
memcpy(myElement->pointerAllocated, m_blockCheckMemory, m_checkBorneSize);
|
||||
#endif
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
memcpy(myElement->pointerAllocated + myElement->sizeUser + m_checkBorneSize, m_blockCheckMemory, m_checkBorneSize);
|
||||
#endif
|
||||
// add to the elements list
|
||||
myElement->used = true;
|
||||
} else {
|
||||
ETK_MEMORY_VERBOSE("MEM allocate (L): %s : %zu Bytes @ (ERROR)", _variableName, myElement->sizeUser);
|
||||
}
|
||||
unLock();
|
||||
// else : no memory allocated ==> nothing to save
|
||||
return myElement->pointerGiveToUser;
|
||||
} else {
|
||||
// if no free handle:
|
||||
void * localPointer = nullptr;
|
||||
localPointer = new char[_num * _size];
|
||||
if (localPointer != nullptr) {
|
||||
ETK_MEMORY_VERBOSE("MEM allocate (-): %s : %lu Bytes @ %p (No log...)", _variableName, _num*_size, localPointer);
|
||||
// set edded memory
|
||||
//addMemory(_num * _size); // not availlable can not un add memory
|
||||
m_totalMemAllocated += _num * _size;
|
||||
} else {
|
||||
ETK_MEMORY_VERBOSE("MEM allocate (-): %s : %lu Bytes @ (ERROR)", _variableName, _num*_size);
|
||||
}
|
||||
unLock();
|
||||
return localPointer;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName) {
|
||||
MemoryElementSystem * myElement;
|
||||
lock();
|
||||
char* asyncFree = nullptr;
|
||||
myElement = getAdressedElement((char*)_pointerData);
|
||||
// check free handle
|
||||
if (myElement != nullptr) {
|
||||
bool errorOccured = false;
|
||||
// We know this element :
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
// check end and Start :
|
||||
if (checkMem(myElement->pointerAllocated) == true) {
|
||||
ETK_MEMORY_ERROR("MEM free (L): %s : %zu Bytes @ %p ==> user @ %p (depassement pre)",_variableName, myElement->sizeUser, myElement->pointerAllocated, myElement->pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (checkMem(myElement->pointerAllocated + myElement->sizeUser + m_checkBorneSize) == true) {
|
||||
ETK_MEMORY_ERROR("MEM free (L): %s : %zu Bytes @ %p ==> user @ %p (depassement post)",_variableName, myElement->sizeUser, myElement->pointerAllocated, myElement->pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (errorOccured == false) {
|
||||
ETK_MEMORY_VERBOSE("MEM free (L): %s : %zu Bytes @ %p ==> user @ %p",_variableName, myElement->sizeUser, myElement->pointerAllocated, myElement->pointerGiveToUser);
|
||||
} else {
|
||||
displayBuffer(myElement->pointerAllocated, myElement->sizeAllocate);
|
||||
//ETK_ASSERT(1 == 0, "Memory error detected");
|
||||
}
|
||||
#else
|
||||
ETK_MEMORY_VERBOSE("MEM free (L): %s : %d Bytes @ %p ==> user @ %p",_variableName, myElement->sizeUser, myElement->pointerAllocated, myElement->pointerGiveToUser);
|
||||
#endif
|
||||
asyncFree = myElement->pointerAllocated;
|
||||
myElement->pointerAllocated = nullptr;
|
||||
removeMemory(myElement->sizeUser);
|
||||
myElement->used = false;
|
||||
}
|
||||
unLock();
|
||||
if (asyncFree != nullptr) {
|
||||
// free Buffer:
|
||||
delete[] asyncFree;
|
||||
return;
|
||||
}
|
||||
//Unknown element
|
||||
ETK_MEMORY_WARNING("MEM free (-): %s : ?? Bytes @ %p ==> unsaved element",_variableName, _pointerData);
|
||||
delete (char*)_pointerData;
|
||||
}
|
||||
|
||||
void displayMemorySize(size_t _size, const char* _name) {
|
||||
if (_size > 1024*1024*1024) {
|
||||
uint32_t teraByte = _size/(1024*1024*1024);
|
||||
uint32_t megaByte = (_size/(1024*1024)%1024);
|
||||
uint32_t kiloByte = (_size/1024) % 1024;
|
||||
uint32_t byte = _size % 1024;
|
||||
ETK_MEMORY_DEBUG("MEM : %s: %4dT %4dM %4dk %4dB", _name, teraByte, megaByte, kiloByte, byte);
|
||||
} else if (_size > 1024*1024) {
|
||||
uint32_t megaByte = _size/(1024*1024);
|
||||
uint32_t kiloByte = (_size/1024) % 1024;
|
||||
uint32_t byte = _size % 1024;
|
||||
ETK_MEMORY_DEBUG("MEM : %s: %4dM %4dk %4dB", _name, megaByte, kiloByte, byte);
|
||||
} else if (m_totalMemAllocated > 1024) {
|
||||
uint32_t megaByte = _size/(1024*1024);
|
||||
uint32_t kiloByte = (_size/1024) % 1024;
|
||||
uint32_t byte = _size % 1024;
|
||||
ETK_MEMORY_DEBUG("MEM : %s: %4dk %4dB", _name, kiloByte, byte);
|
||||
} else {
|
||||
uint32_t megaByte = _size/(1024*1024);
|
||||
uint32_t kiloByte = (_size/1024) % 1024;
|
||||
uint32_t byte = _size % 1024;
|
||||
ETK_MEMORY_DEBUG("MEM : %s: %4dB", _name, byte);
|
||||
}
|
||||
}
|
||||
|
||||
void display(bool _statusOnly) {
|
||||
lock();
|
||||
ETK_MEMORY_DEBUG("MEM: Log : ------------------------------");
|
||||
ETK_MEMORY_DEBUG("MEM: (current/total) allocation: %ld / %ld ", int64_t(m_currentMemAllocatedCount), uint64_t(m_dynamicID));
|
||||
for (int32_t iii=0; iii<64; ++iii) {
|
||||
if (m_currentMemAllocatedCountSize[iii] != 0) {
|
||||
ETK_MEMORY_DEBUG("MEM: Number (current/Total) of allocation: 2<<%2d: %8ld / %8ld %9ld Bytes",
|
||||
iii,
|
||||
uint64_t(m_currentMemAllocatedCountSize[iii]),
|
||||
uint64_t(m_totalMemAllocatedCountSize[iii]),
|
||||
(uint64_t(1)<<iii));
|
||||
}
|
||||
}
|
||||
ETK_MEMORY_DEBUG("MEM: number of element that can be registered %ld", m_memListElementSize);
|
||||
displayMemorySize(m_memListElementSize*sizeof(MemoryElementSystem) + sizeof(memoryAllocatorHandle), "System allocator ");
|
||||
displayMemorySize(m_totalMemAllocated, "Total allocated ");
|
||||
displayMemorySize(m_currentMemAllocated, "Total Current Use ");
|
||||
displayMemorySize(m_maxMemoryAllocated, "Max simultaneous Use ");
|
||||
if (_statusOnly == true) {
|
||||
unLock();
|
||||
return;
|
||||
}
|
||||
ETK_MEMORY_DEBUG("MEM : Log : ----------- Memory -----------");
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
displayMemoryProperty(m_memListElements[iii]);
|
||||
}
|
||||
}
|
||||
ETK_MEMORY_DEBUG("MEM : -----------------------------------");
|
||||
unLock();
|
||||
}
|
||||
|
||||
bool check() {
|
||||
bool detectError = false;
|
||||
lock();
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
#if ETK_MEMORY_CHECKER > 1
|
||||
bool errorOccured = false;
|
||||
if (checkMem(m_memListElements[iii].pointerAllocated) == true) {
|
||||
ETK_MEMORY_ERROR("MEM CHECK (L): %s : %ld Bytes @ %p ==> user @ %p (depassement pre)",m_memListElements[iii].variableName, m_memListElements[iii].sizeUser, m_memListElements[iii].pointerAllocated, m_memListElements[iii].pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (checkMem(m_memListElements[iii].pointerAllocated + m_memListElements[iii].sizeUser + m_checkBorneSize) == true) {
|
||||
ETK_MEMORY_ERROR("MEM CHECK (L): %s : %ld Bytes @ %p ==> user @ %p (depassement post)",m_memListElements[iii].variableName, m_memListElements[iii].sizeUser, m_memListElements[iii].pointerAllocated, m_memListElements[iii].pointerGiveToUser);
|
||||
errorOccured = true;
|
||||
}
|
||||
if (errorOccured == true) {
|
||||
detectError = true;
|
||||
displayBuffer(m_memListElements[iii].pointerAllocated, m_memListElements[iii].sizeAllocate);
|
||||
// Clean all the erreor to prevent the other error display
|
||||
memcpy(m_memListElements[iii].pointerAllocated, m_blockCheckMemory, m_checkBorneSize);
|
||||
// Clean all the erreor to prevent the other error display
|
||||
memcpy(m_memListElements[iii].pointerAllocated + m_memListElements[iii].sizeUser + m_checkBorneSize, m_blockCheckMemory, m_checkBorneSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
unLock();
|
||||
return detectError;
|
||||
}
|
||||
|
||||
bool checkPointer(void* _pointer) {
|
||||
lock();
|
||||
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
|
||||
if (m_memListElements[iii].used == true) {
|
||||
bool find = false;
|
||||
if (m_memListElements[iii].pointerAllocated == _pointer) {
|
||||
find = true;
|
||||
}
|
||||
if (m_memListElements[iii].pointerGiveToUser == _pointer) {
|
||||
find = true;
|
||||
}
|
||||
if (find == true) {
|
||||
unLock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
unLock();
|
||||
ETK_MEMORY_ERROR("MEM Check pointer: Can not find the pointer in the system DB...");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// This permit to initialize the handle just in time ...
|
||||
static memoryAllocatorHandle& getHandle() {
|
||||
static memoryAllocatorHandle tmp;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
uint64_t* etk::memory::createSnapshoot() {
|
||||
return getHandle().createSnapshoot();
|
||||
}
|
||||
|
||||
bool etk::memory::checkSnapshoot(uint64_t* _handle) {
|
||||
return getHandle().checkSnapshoot(_handle);
|
||||
}
|
||||
|
||||
void etk::memory::clearSnapshoot(uint64_t* _handle) {
|
||||
getHandle().clearSnapshoot(_handle);
|
||||
}
|
||||
|
||||
void* etk::memory::allocate(size_t _num,
|
||||
size_t _size,
|
||||
const char* _variableName,
|
||||
const char* _functionName,
|
||||
int32_t _line,
|
||||
const char* _fileName) {
|
||||
return getHandle().allocate(_num, _size, _variableName, _functionName, _line, _fileName);
|
||||
}
|
||||
|
||||
void etk::memory::remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName) {
|
||||
getHandle().remove(_pointerData, _variableName, _functionName, _line, _fileName);
|
||||
}
|
||||
|
||||
void etk::memory::display(bool _statusOnly) {
|
||||
getHandle().display(_statusOnly);
|
||||
}
|
||||
|
||||
bool etk::memory::check() {
|
||||
return getHandle().check();
|
||||
}
|
||||
|
||||
bool etk::memory::checkPointer(void* _pointer) {
|
||||
return getHandle().checkPointer(_pointer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -16,3 +16,170 @@
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ETK_MEMORY_CHECKER 2
|
||||
|
||||
#ifndef ETK_MEMORY_CHECKER
|
||||
#define ETK_MEMORY_CHECKER 0
|
||||
#endif
|
||||
|
||||
#if ETK_MEMORY_CHECKER >= 0
|
||||
namespace etk {
|
||||
namespace memory {
|
||||
/**
|
||||
* @brief Create an allocation memory and set start and stop header. Log in the curent structure.
|
||||
* If no more free element in the basic structure, the system allocate without saving information and header start and stop
|
||||
* @param[in] _num number of alament needed to allocate
|
||||
* @param[in] _size Size of one element to allocate
|
||||
* @param[in] _variableName Variable name to allocate (must be a real static cont never removed)
|
||||
* @param[in] _functionName Fonction Name where allocation is done (must be a real static cont never removed)
|
||||
* @param[in] _line Line where allocation is done.
|
||||
* @param[in] _fileName File where allocation is done. (must be a real static cont never removed)
|
||||
* @return pointer on the current memory allocation. (or NULL if an error occured)
|
||||
*/
|
||||
void* allocate(size_t _num, size_t _size, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName);
|
||||
/**
|
||||
* @brief Free Memory with the dedicate pointer
|
||||
* If the memory is not saved the current pointer is free, else we get the real pointer and free it
|
||||
* @param[in,out] _pointerData User pointer Data.
|
||||
* @param[in] _variableName Variable name where free is done. (must be a real static cont never removed)
|
||||
* @param[in] _functionName Fonction name where free is done. (must be a real static cont never removed)
|
||||
* @param[in] _line line where free is done.
|
||||
* @param[in] _fileName file where free is done. (must be a real static cont never removed)
|
||||
*/
|
||||
void remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName);
|
||||
/**
|
||||
* @brief Display all memory not free by this system.
|
||||
* @param[in] _statusOnly Display only the memory allocation status.
|
||||
*/
|
||||
void display(bool _statusOnly=true);
|
||||
/**
|
||||
* @brief Check if memory have not write out of the range.
|
||||
*/
|
||||
bool check();
|
||||
/**
|
||||
* @brief Check if the pointer is already register in the allocator (can not predist the size, but permti to know where the error came from in debug mode
|
||||
* @param[in] _pointerPointer on the data to check
|
||||
* @return true the pointer is set
|
||||
* @return false the pointer is not set
|
||||
*/
|
||||
bool checkPointer(void* _pointer);
|
||||
/**
|
||||
* @brief Create a snapshoot of the memory
|
||||
* @return handle on the snapshoot
|
||||
*/
|
||||
uint64_t* createSnapshoot();
|
||||
/**
|
||||
* @brief Check if a snapshoot is correct (no change)
|
||||
* @param[in] _handle Handle on the snapshoot
|
||||
* @return true the memory is identical
|
||||
*/
|
||||
bool checkSnapshoot(uint64_t* _handle);
|
||||
/**
|
||||
* @brief Free the snapshoot handle
|
||||
* @param[in] _handle Handle on the snapshoot
|
||||
*/
|
||||
void clearSnapshoot(uint64_t* _handle);
|
||||
|
||||
template<class ETK_TYPE,
|
||||
class... ETK_MEMORY_ARGS>
|
||||
ETK_TYPE* allocatorNew(ETK_MEMORY_ARGS&& ... _args) {
|
||||
char* tmp = (char*)etk::memory::allocate(1, sizeof(ETK_TYPE), "new", __func__, __LINE__, __FILE__);
|
||||
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
||||
}
|
||||
template<class ETK_TYPE,
|
||||
class... ETK_MEMORY_ARGS>
|
||||
ETK_TYPE* allocatorNewSize(size_t _size, ETK_MEMORY_ARGS&& ... _args) {
|
||||
char* tmp = (char*)etk::memory::allocate(_size, sizeof(ETK_TYPE), "new", __func__, __LINE__, __FILE__);
|
||||
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
||||
}
|
||||
template<class ETK_TYPE,
|
||||
class... ETK_MEMORY_ARGS>
|
||||
ETK_TYPE* allocatorNewFull(const char* _variableName,
|
||||
const char* _functionName,
|
||||
int32_t _line,
|
||||
const char* _fileName,
|
||||
ETK_MEMORY_ARGS&& ... _args) {
|
||||
char* tmp = (char*)etk::memory::allocate(1, sizeof(ETK_TYPE), _variableName, _functionName, _line, _fileName);
|
||||
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
||||
}
|
||||
template<class ETK_TYPE>
|
||||
void allocatorDelete(ETK_TYPE* _element,
|
||||
const char* _variableName = "",
|
||||
const char* _functionName = "",
|
||||
int32_t _line = __LINE__,
|
||||
const char* _fileName = __FILE__) {
|
||||
if (_element == nullptr) {
|
||||
return;
|
||||
}
|
||||
_element->~ETK_TYPE();
|
||||
etk::memory::remove((void*)_element, _variableName, _functionName, _line, _fileName);
|
||||
_element = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ETK_NEW(type, ...) \
|
||||
new ((char*)etk::memory::allocate(1, sizeof(type), #type, __func__, __LINE__, __FILE__)) type(__VA_ARGS__)
|
||||
|
||||
#define ETK_DELETE(type, pointerData) \
|
||||
etk::memory::allocatorDelete((type*)(pointerData), #type, __func__, __LINE__, __FILE__)
|
||||
|
||||
#define ETK_MALLOC(type, nbElements) \
|
||||
((type *)etk::memory::allocate( (nbElements), sizeof(type), #type, __func__, __LINE__, __FILE__))
|
||||
|
||||
#define ETK_FREE(type, pointerData) \
|
||||
etk::memory::remove( (pointerData), #type, __func__, __LINE__, __FILE__)
|
||||
|
||||
#define ETK_MEM_SHOW_LOG(...) \
|
||||
etk::memory::display(__VA_ARGS__)
|
||||
|
||||
#define ETK_MEM_CHECK() \
|
||||
etk::memory::check()
|
||||
#else
|
||||
namespace etk {
|
||||
namespace memory {
|
||||
template<class ETK_TYPE,
|
||||
class... T_ARGS>
|
||||
ETK_TYPE* allocatorNew(T_ARGS&& ... _args) {
|
||||
return new ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
||||
}
|
||||
template<class ETK_TYPE,
|
||||
class... T_ARGS>
|
||||
ETK_TYPE* allocatorNewFull(const char* _variableName,
|
||||
const char* _functionName,
|
||||
int32_t _line,
|
||||
const char* _fileName,
|
||||
ETK_MEMORY_ARGS&& ... _args) {
|
||||
return new ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
||||
}
|
||||
template<class ETK_TYPE>
|
||||
void allocatorDelete(ETK_TYPE* _element,
|
||||
const char* _variableName = "",
|
||||
const char* _functionName = "",
|
||||
int32_t _line = __LINE__,
|
||||
const char* _fileName = __FILE__) {
|
||||
delete _element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ETK_NEW(type, ...) \
|
||||
new type(__VA_ARGS__)
|
||||
|
||||
#define ETK_DELETE(type, pointerData) \
|
||||
delete ((type*)(pointerData))
|
||||
|
||||
#define ETK_MALLOC(dataType, nbElements) \
|
||||
((dataType *)new dataType[nbElements]
|
||||
|
||||
#define ETK_FREE(type, pointerData) \
|
||||
delete[] (type*)pointerData
|
||||
|
||||
#define ETK_MEM_SHOW_LOG(...) \
|
||||
do { } while(false)
|
||||
|
||||
#define ETK_MEM_CHECK() \
|
||||
do {} while(false)
|
||||
|
||||
#endif
|
||||
|
@ -40,12 +40,12 @@ namespace etk {
|
||||
public:
|
||||
FunctionPrivateLambda(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
||||
m_dataPointer(_functor) {
|
||||
ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
|
||||
ETK_FUNCTION_DEBUG(" CREATE FunctionPrivateLambda \n");
|
||||
}
|
||||
/*
|
||||
FunctionPrivateLambda(const ETK_TYPE_FUNCTION_FUNCTOR& _functor):
|
||||
m_dataPointer(_functor) {
|
||||
ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
|
||||
ETK_FUNCTION_DEBUG(" CREATE FunctionPrivateLambda \n");
|
||||
}
|
||||
*/
|
||||
~FunctionPrivateLambda() {
|
||||
@ -56,7 +56,7 @@ namespace etk {
|
||||
}
|
||||
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() {
|
||||
ETK_FUNCTION_DEBUG(" COPY FunctionPrivateLambda \n");
|
||||
return new FunctionPrivateLambda(m_dataPointer);
|
||||
return ETK_NEW(FunctionPrivateLambda, m_dataPointer);
|
||||
}
|
||||
};
|
||||
|
||||
@ -67,34 +67,35 @@ namespace etk {
|
||||
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
|
||||
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
|
||||
private:
|
||||
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* m_pointerPrivate;
|
||||
typedef FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> FunctionPrivateTypedef;
|
||||
FunctionPrivateTypedef* m_pointerPrivate;
|
||||
uint32_t m_pppppp;
|
||||
public:
|
||||
Function():
|
||||
m_pointerPrivate(nullptr) {
|
||||
m_pppppp = MM___pppppp++;
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 1 \n", m_pppppp, (uint64_t)this);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function 1 \n", m_pppppp, (uint64_t)this);
|
||||
}
|
||||
Function(const etk::NullPtr&):
|
||||
m_pointerPrivate(nullptr) {
|
||||
m_pppppp = MM___pppppp++;
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 2\n", m_pppppp, (uint64_t)this);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function 2\n", m_pppppp, (uint64_t)this);
|
||||
}
|
||||
Function(const Function& _obj):
|
||||
m_pointerPrivate(nullptr) {
|
||||
m_pppppp = MM___pppppp++;
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ---------------------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function (copy constructor) ---------------------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
|
||||
if (_obj.m_pointerPrivate != nullptr) {
|
||||
m_pointerPrivate = _obj.m_pointerPrivate->copy();
|
||||
}
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ------- (done) ------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function (copy constructor) ------- (done) ------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj);
|
||||
}
|
||||
Function(Function&& _obj):
|
||||
m_pointerPrivate(nullptr) {
|
||||
m_pppppp = MM___pppppp++;
|
||||
ETK_FUNCTION_DEBUG("[%d] new Function 2\n", m_pppppp);
|
||||
ETK_FUNCTION_DEBUG("[%d] create Function 2\n", m_pppppp);
|
||||
_obj.swap(*this);
|
||||
ETK_FUNCTION_DEBUG("[%d] new Function 2 (done)\n", m_pppppp);
|
||||
ETK_FUNCTION_DEBUG("[%d] create Function 2 (done)\n", m_pppppp);
|
||||
}
|
||||
template <typename ETK_TYPE_FUNCTION_FUNCTOR,
|
||||
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
|
||||
@ -104,13 +105,14 @@ namespace etk {
|
||||
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
||||
m_pointerPrivate(nullptr) {
|
||||
m_pppppp = MM___pppppp++;
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 \n", m_pppppp, (uint64_t)this);
|
||||
m_pointerPrivate = new FunctionPrivateLambda<ETK_TYPE_FUNCTION_FUNCTOR, ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>(_functor);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 (done)\n", m_pppppp, (uint64_t)this);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function 4 \n", m_pppppp, (uint64_t)this);
|
||||
typedef FunctionPrivateLambda<ETK_TYPE_FUNCTION_FUNCTOR, ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> FunctionPrivateLambdaTypedef;
|
||||
m_pointerPrivate = ETK_NEW(FunctionPrivateLambdaTypedef, _functor);
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function 4 (done)\n", m_pppppp, (uint64_t)this);
|
||||
}
|
||||
~Function() {
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] DELETE Function \n", m_pppppp, (uint64_t)this);
|
||||
delete m_pointerPrivate;
|
||||
ETK_DELETE(FunctionPrivateTypedef, m_pointerPrivate);
|
||||
m_pointerPrivate = nullptr;
|
||||
}
|
||||
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
|
||||
@ -134,7 +136,7 @@ namespace etk {
|
||||
return *this;
|
||||
}
|
||||
Function& operator= (etk::NullPtr _obj) {
|
||||
delete m_pointerPrivate;
|
||||
ETK_DELETE(FunctionPrivateTypedef, m_pointerPrivate);
|
||||
m_pointerPrivate = nullptr;
|
||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = nullptr 0X%lx\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate);
|
||||
return *this;
|
||||
|
18
etk/Map.hpp
18
etk/Map.hpp
@ -8,6 +8,7 @@
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Pair.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/Allocator.hpp>
|
||||
|
||||
namespace etk {
|
||||
/**
|
||||
@ -111,7 +112,7 @@ namespace etk {
|
||||
}
|
||||
/**
|
||||
* @brief Incremental operator
|
||||
* @return Reference on a new iterator and increment the other one
|
||||
* @return Reference on an iterator and increment the other one
|
||||
*/
|
||||
Iterator operator++ (int32_t) {
|
||||
Iterator it(*this);
|
||||
@ -120,7 +121,7 @@ namespace etk {
|
||||
}
|
||||
/**
|
||||
* @brief Decremental operator
|
||||
* @return Reference on a new iterator and decrement the other one
|
||||
* @return Reference on an iterator and decrement the other one
|
||||
*/
|
||||
Iterator operator-- (int32_t) {
|
||||
Iterator it(*this);
|
||||
@ -242,7 +243,8 @@ namespace etk {
|
||||
typedef bool (*sortFunction)(etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* const & _key1,
|
||||
etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* const & _key2);
|
||||
private:
|
||||
etk::Vector<etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>*> m_data; //!< Data of the Map ==> the Map table is composed of pointer, this permit to have high speed when resize the vector ...
|
||||
typedef etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA> pairType;
|
||||
etk::Vector<pairType*> m_data; //!< Data of the Map ==> the Map table is composed of pointer, this permit to have high speed when resize the vector ...
|
||||
sortFunction m_comparator;
|
||||
public:
|
||||
/**
|
||||
@ -296,7 +298,7 @@ namespace etk {
|
||||
if (it == nullptr) {
|
||||
continue;
|
||||
}
|
||||
m_data.pushBack(new etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>(it->first, it->second));
|
||||
m_data.pushBack(ETK_NEW(pairType, it->first, it->second));
|
||||
}
|
||||
}
|
||||
void setOrdered(bool _ordered) {
|
||||
@ -350,7 +352,7 @@ namespace etk {
|
||||
void clear() {
|
||||
for (auto &it : m_data) {
|
||||
if (it != nullptr) {
|
||||
delete(it);
|
||||
ETK_DELETE(pairType, it);
|
||||
it=nullptr;
|
||||
}
|
||||
}
|
||||
@ -425,7 +427,7 @@ namespace etk {
|
||||
void add(const ETK_MAP_TYPE_KEY& _key, const ETK_MAP_TYPE_DATA& _value) {
|
||||
int64_t elementId = getId(_key);
|
||||
if (elementId <0) {
|
||||
etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* tmp = new etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>(etk::move(_key), etk::move(_value));
|
||||
etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* tmp = ETK_NEW(pairType, etk::move(_key), etk::move(_value));
|
||||
if (tmp == nullptr) {
|
||||
return;
|
||||
}
|
||||
@ -457,7 +459,7 @@ namespace etk {
|
||||
//nothing to do ==> not existed
|
||||
return;
|
||||
}
|
||||
delete(m_data[elementId]);
|
||||
ETK_DELETE(pairType, m_data[elementId]);
|
||||
m_data[elementId] = nullptr;
|
||||
m_data.erase(m_data.begin()+elementId);
|
||||
}
|
||||
@ -467,7 +469,7 @@ namespace etk {
|
||||
*/
|
||||
Iterator erase(const Iterator& _it) {
|
||||
int64_t elementId = _it.m_current;
|
||||
delete(m_data[elementId]);
|
||||
ETK_DELETE(pairType, m_data[elementId]);
|
||||
m_data[elementId] = nullptr;
|
||||
m_data.erase(m_data.begin()+elementId);
|
||||
return position(elementId);
|
||||
|
@ -792,7 +792,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
~NodePTheseElement() {
|
||||
/*
|
||||
for (auto it : m_subNode) {
|
||||
delete *it;
|
||||
ETK_DELETE(Node<CLASS_TYPE>, *it);
|
||||
*it = nullptr;
|
||||
}
|
||||
*/
|
||||
@ -813,7 +813,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||
}
|
||||
// add to the under-node list :
|
||||
m_subNode.pushBack(new NodePThese<CLASS_TYPE>(tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
m_subNode.pushBack(ETK_NEW(NodePThese<CLASS_TYPE>, tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
// move current position ...
|
||||
pos += elementSize+1;
|
||||
}
|
||||
@ -827,7 +827,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||
}
|
||||
// add to the under-node list :
|
||||
m_subNode.pushBack(new NodeBracket<CLASS_TYPE>(tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
m_subNode.pushBack(ETK_NEW(NodeBracket<CLASS_TYPE>, tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
// move current position ...
|
||||
pos += elementSize+1;
|
||||
}
|
||||
@ -869,7 +869,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
return false;
|
||||
case regexOpcodeEOF:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("EOF");
|
||||
tmpNode->addValue('\0');
|
||||
tmpNode->setCountOutput(false);
|
||||
@ -879,7 +879,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeDot:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("dot");
|
||||
tmpNode->addValue('\0');
|
||||
tmpNode->setInvert(true);
|
||||
@ -887,11 +887,11 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
}
|
||||
break;
|
||||
case regexOpcodeStartOfLine:
|
||||
m_subNode.pushBack(new NodeSOL<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
m_subNode.pushBack(ETK_NEW(NodeSOL<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
break;
|
||||
case regexOpcodeEndOfLine:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("EOL");
|
||||
tmpNode->addValue('\n');
|
||||
m_subNode.pushBack(tmpNode);
|
||||
@ -899,7 +899,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeDigit:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("digit");
|
||||
tmpNode->addRange('0', '9');
|
||||
m_subNode.pushBack(tmpNode);
|
||||
@ -907,7 +907,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeDigitNot:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("digit-not");
|
||||
tmpNode->addRange('0', '9');
|
||||
tmpNode->setInvert(true);
|
||||
@ -916,7 +916,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeLetter:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("letter");
|
||||
tmpNode->addRange('a', 'z');
|
||||
tmpNode->addRange('A', 'Z');
|
||||
@ -925,7 +925,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeLetterNot:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("letter-not");
|
||||
tmpNode->addRange('a', 'z');
|
||||
tmpNode->addRange('A', 'Z');
|
||||
@ -935,7 +935,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeSpace:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("space");
|
||||
tmpNode->addValue(' ');
|
||||
tmpNode->addValue('\t');
|
||||
@ -948,7 +948,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeSpaceNot:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("space-not");
|
||||
tmpNode->addValue(' ');
|
||||
tmpNode->addValue('\t');
|
||||
@ -962,7 +962,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeWord:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("word");
|
||||
tmpNode->addRange('a', 'z');
|
||||
tmpNode->addRange('A', 'Z');
|
||||
@ -972,7 +972,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
break;
|
||||
case regexOpcodeWordNot:
|
||||
{
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = new NodeRangeValue<CLASS_TYPE>(Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
NodeRangeValue<CLASS_TYPE>* tmpNode = ETK_NEW(NodeRangeValue<CLASS_TYPE>, Node<CLASS_TYPE>::m_nodeLevel+1);
|
||||
tmpNode->setDescriptiveName("word-not");
|
||||
tmpNode->addRange('a', 'z');
|
||||
tmpNode->addRange('A', 'Z');
|
||||
@ -987,7 +987,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||
}
|
||||
// add to the under-node list :
|
||||
m_subNode.pushBack(new NodeValue<CLASS_TYPE>(tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
m_subNode.pushBack(ETK_NEW(NodeValue<CLASS_TYPE>, tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
// move current position ...
|
||||
pos += elementSize-1;
|
||||
}
|
||||
@ -1142,7 +1142,7 @@ template<class CLASS_TYPE> class NodePThese : public Node<CLASS_TYPE> {
|
||||
~NodePThese() {
|
||||
/*
|
||||
for (auto it : m_subNode) {
|
||||
delete *it;
|
||||
ETK_DELETE(Node<CLASS_TYPE>, *it);
|
||||
*it = nullptr;
|
||||
}
|
||||
*/
|
||||
@ -1162,7 +1162,7 @@ template<class CLASS_TYPE> class NodePThese : public Node<CLASS_TYPE> {
|
||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||
}
|
||||
// add to the under-node list :
|
||||
m_subNode.pushBack(new NodePTheseElement<CLASS_TYPE>(tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
m_subNode.pushBack(ETK_NEW(NodePTheseElement<CLASS_TYPE>, tmpData, Node<CLASS_TYPE>::m_nodeLevel+1));
|
||||
pos += elementSize+1;
|
||||
TK_REG_DEBUG("plop=" << createString(Node<CLASS_TYPE>::m_regExData, pos, pos+1) );
|
||||
elementSize = getLenOfPTheseElement(Node<CLASS_TYPE>::m_regExData, pos);
|
||||
@ -1434,8 +1434,8 @@ template<class CLASS_TYPE> class RegEx {
|
||||
m_maximize = _value;
|
||||
}
|
||||
/**
|
||||
* @brief Set a new regular expression matching
|
||||
* @param[in] _expression the new expression to search
|
||||
* @brief Set a regular expression matching
|
||||
* @param[in] _expression the expression to search
|
||||
*/
|
||||
// TODO : Add an error ...
|
||||
void compile(const etk::String &_expression) {
|
||||
|
@ -8,12 +8,12 @@
|
||||
#include <etk/String.hpp>
|
||||
|
||||
etk::Stream::Stream(size_t _basicSize) :
|
||||
m_data(new etk::String) {
|
||||
|
||||
m_data(ETK_NEW(etk::String)) {
|
||||
m_data->reserve(_basicSize);
|
||||
}
|
||||
|
||||
etk::Stream::~Stream() {
|
||||
delete m_data;
|
||||
ETK_DELETE(etk::String, m_data);
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
|
115
etk/String.cpp
115
etk/String.cpp
@ -3,13 +3,41 @@
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/UString.hpp>
|
||||
|
||||
|
||||
|
||||
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING > 0
|
||||
const size_t etk::String::m_sizeLocal = 64-sizeof(etk::Vector<char>);
|
||||
#else
|
||||
const char* getStaticEmptyString() {
|
||||
static const char* tmp = "\0\0\0\0\0\0";
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
etk::String::String():
|
||||
m_data() {
|
||||
m_data.resize(1, '\0');
|
||||
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING > 0
|
||||
static_assert(sizeof(etk::String) == ETK_ENABLE_INTERNAL_DATA_IN_STRING, "Wrong basic size of string");
|
||||
//printf("size of string=%ld %ld %ld\n", uint64_t(sizeof(etk::String)), m_sizeLocal, uint64_t(sizeof(etk::Vector<char>)));
|
||||
memset(m_localData, 0, sizeof(m_localData));
|
||||
#else
|
||||
//m_data.resize(1, '\0');
|
||||
#endif
|
||||
}
|
||||
|
||||
etk::String::String(const etk::String& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING > 0
|
||||
if (_obj.size() < sizeof(m_localData)) {
|
||||
if (_obj.m_data.size() != 0) {
|
||||
memcpy(m_localData, &_obj.m_data[0], _obj.m_data.size());
|
||||
} else {
|
||||
memcpy(m_localData, _obj.m_localData, sizeof(m_localData));
|
||||
}
|
||||
} else {
|
||||
m_data = _obj.m_data;
|
||||
}
|
||||
#else
|
||||
m_data = _obj.m_data;
|
||||
#endif
|
||||
}
|
||||
|
||||
etk::String::String(const etk::String& _obj, size_t _pos, size_t _size) {
|
||||
@ -17,10 +45,25 @@ etk::String::String(const etk::String& _obj, size_t _pos, size_t _size) {
|
||||
_size = etk::String::npos;
|
||||
}
|
||||
if (_size != etk::String::npos) {
|
||||
resize(_size);
|
||||
for (size_t iii=0; iii<_size; ++iii) {
|
||||
m_data[iii] = _obj.m_data[_pos+iii];
|
||||
}
|
||||
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING > 0
|
||||
if (_size < sizeof(m_localData)) {
|
||||
if (_obj.m_data.size() != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
resize(_size);
|
||||
for (size_t iii=0; iii<_size; ++iii) {
|
||||
m_data[iii] = _obj.m_data[_pos+iii];
|
||||
}
|
||||
}
|
||||
#else
|
||||
resize(_size);
|
||||
for (size_t iii=0; iii<_size; ++iii) {
|
||||
m_data[iii] = _obj.m_data[_pos+iii];
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
resize(_obj.size()-_pos);
|
||||
@ -35,11 +78,16 @@ etk::String::String(const char* _obj) {
|
||||
return;
|
||||
}
|
||||
uint32_t size = strlen(_obj);
|
||||
/*if (size == 0) {
|
||||
return;
|
||||
}*/
|
||||
resize(size);
|
||||
for (size_t iii=0; iii<size; ++iii) {
|
||||
m_data[iii] = _obj[iii];
|
||||
}
|
||||
//printf(" size=%d with='%s' ==> '%s'\n", size, _obj, &m_data[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
etk::String::String(const etk::String _obj) {
|
||||
resize(_obj.size());
|
||||
@ -161,7 +209,11 @@ etk::String& etk::String::operator+= (char _value) {
|
||||
// Return the current pointer
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t etk::String::size() const {
|
||||
if (m_data.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return m_data.size() - 1; // remove '\0'
|
||||
}
|
||||
|
||||
@ -199,7 +251,7 @@ void etk::String::pushBack(const char* _item, size_t _nbElement) {
|
||||
}
|
||||
|
||||
void etk::String::popBack() {
|
||||
if(size()>0) {
|
||||
if(size() > 0) {
|
||||
resize(size()-1);
|
||||
}
|
||||
}
|
||||
@ -209,7 +261,7 @@ void etk::String::reserve(size_t _size) {
|
||||
}
|
||||
|
||||
void etk::String::clear() {
|
||||
resize(0);
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
void etk::String::insert(size_t _pos, const char* _item, size_t _nbElement) {
|
||||
@ -267,7 +319,7 @@ void etk::String::erase(size_t _pos, size_t _nbElement) {
|
||||
}
|
||||
|
||||
void etk::String::eraseRange(size_t _pos, size_t _posEnd) {
|
||||
if (_pos>size()) {
|
||||
if (_pos > size()) {
|
||||
//TK_ERROR(" can not Erase Element at this position : " << _pos << " > " << size());
|
||||
return;
|
||||
}
|
||||
@ -278,7 +330,7 @@ void etk::String::eraseRange(size_t _pos, size_t _posEnd) {
|
||||
size_t tmpSize = size();
|
||||
// move current data
|
||||
size_t sizeToMove = (tmpSize - (_pos+nbElement));
|
||||
if ( 0 < sizeToMove) {
|
||||
if (sizeToMove > 0) {
|
||||
for (size_t iii=0; iii<sizeToMove; iii++) {
|
||||
m_data[_pos+iii] = m_data[_pos+nbElement+iii];
|
||||
}
|
||||
@ -289,10 +341,10 @@ void etk::String::eraseRange(size_t _pos, size_t _posEnd) {
|
||||
|
||||
etk::String etk::String::extract(size_t _posStart, size_t _posEnd) const {
|
||||
etk::String out;
|
||||
if (_posStart >= size() ) {
|
||||
if (_posStart >= size()) {
|
||||
return out;
|
||||
}
|
||||
if (_posEnd >= size() ) {
|
||||
if (_posEnd >= size()) {
|
||||
_posEnd = size();
|
||||
}
|
||||
out.pushBack(&m_data[_posStart], _posEnd-_posStart);
|
||||
@ -300,6 +352,9 @@ etk::String etk::String::extract(size_t _posStart, size_t _posEnd) const {
|
||||
}
|
||||
|
||||
const char* etk::String::c_str() const {
|
||||
if (m_data.size() == 0) {
|
||||
return getStaticEmptyString();
|
||||
}
|
||||
return &m_data[0];
|
||||
}
|
||||
|
||||
@ -320,14 +375,18 @@ const etk::String::Iterator etk::String::begin() const {
|
||||
}
|
||||
|
||||
etk::String::Iterator etk::String::end() {
|
||||
return position( size() );
|
||||
return position(size());
|
||||
}
|
||||
|
||||
const etk::String::Iterator etk::String::end() const {
|
||||
return position( size() );
|
||||
return position(size());
|
||||
}
|
||||
|
||||
void etk::String::resize(size_t _newSize, char _value) {
|
||||
if (_newSize == 0) {
|
||||
m_data.clear();
|
||||
return;
|
||||
}
|
||||
size_t oldSize = m_data.size();
|
||||
if (oldSize != 0) {
|
||||
m_data[m_data.size()-1] = _value;
|
||||
@ -342,7 +401,7 @@ bool etk::String::operator== (const etk::String& _obj) const {
|
||||
if( this == &_obj ) {
|
||||
return true;
|
||||
}
|
||||
// first step : check the size ...
|
||||
// first step: check the size...
|
||||
if (m_data.size() != _obj.m_data.size()) {
|
||||
return false;
|
||||
}
|
||||
@ -359,7 +418,7 @@ bool etk::String::operator!= (const etk::String& _obj) const {
|
||||
if( this == &_obj ) {
|
||||
return false;
|
||||
}
|
||||
// first step : check the size ...
|
||||
// first step: check the size...
|
||||
if (m_data.size() != _obj.m_data.size()) {
|
||||
return true;
|
||||
}
|
||||
@ -371,6 +430,26 @@ bool etk::String::operator!= (const etk::String& _obj) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
char& etk::String::get(size_t _pos) {
|
||||
if (m_data.size() == 0) {
|
||||
return (char&)(getStaticEmptyString()[_pos]);
|
||||
}
|
||||
return m_data[_pos];
|
||||
}
|
||||
|
||||
char& etk::String::operator[] (size_t _pos) {
|
||||
if (m_data.size() == 0) {
|
||||
return (char&)(getStaticEmptyString()[_pos]);
|
||||
}
|
||||
return m_data[_pos];
|
||||
}
|
||||
|
||||
const char& etk::String::operator[] (size_t _pos) const {
|
||||
if (m_data.size() == 0) {
|
||||
return getStaticEmptyString()[_pos];
|
||||
}
|
||||
return m_data[_pos];
|
||||
}
|
||||
|
||||
char etk::toLower(char _value) {
|
||||
if ( _value >= 'A'
|
||||
@ -1157,7 +1236,7 @@ char etk::toHexChar(uint8_t _value) {
|
||||
etk::String etk::toHex(uint64_t _value, uint32_t _size) {
|
||||
etk::String out;
|
||||
for (int32_t iii = 15; iii >=0; --iii) {
|
||||
if ( _size >= iii
|
||||
if ( _size >= uint64_t(iii)
|
||||
|| _value >= uint64_t(1)<<iii) {
|
||||
out += etk::toHexChar((_value>>(iii*4)) & 0x0F);
|
||||
}
|
||||
@ -1169,7 +1248,7 @@ etk::String etk::toHex(uint64_t _value, uint32_t _size) {
|
||||
etk::String etk::toBin(uint64_t _value, uint32_t _size) {
|
||||
etk::String out;
|
||||
for (int32_t iii = 63; iii >=0; --iii) {
|
||||
if ( _size >= iii
|
||||
if ( _size >= uint64_t(iii)
|
||||
|| _value >= uint64_t(1)<<iii) {
|
||||
out += etk::toHexChar((_value>>(iii)) & 0x01);
|
||||
}
|
||||
|
@ -9,6 +9,11 @@
|
||||
//#include <etk/debug.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
// This permit to define a minimal size in the string to permit to optimise the unneeded allocation of memory (32 remove allocation of 1 byte and 64 remove multiple allocation of 16 bytes (common)
|
||||
#ifndef ETK_ENABLE_INTERNAL_DATA_IN_STRING
|
||||
// TODO: NOTE: This is really not functionnal for now...
|
||||
//#define ETK_ENABLE_INTERNAL_DATA_IN_STRING 64
|
||||
#endif
|
||||
|
||||
namespace etk {
|
||||
/**
|
||||
@ -19,7 +24,7 @@ namespace etk {
|
||||
class Iterator {
|
||||
private:
|
||||
size_t m_current; //!< current Id on the string
|
||||
String* m_string; //!< Pointer on the current element of the stringBin
|
||||
String* m_string; //!< Pointer on the current element of the string
|
||||
public:
|
||||
/**
|
||||
* @brief Basic iterator constructor with no link with an etk::String
|
||||
@ -201,6 +206,10 @@ namespace etk {
|
||||
};
|
||||
private:
|
||||
etk::Vector<char> m_data; //!< pointer on the current data (contain all time 1 element '\0')
|
||||
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING >= 32
|
||||
char m_localData[ETK_ENABLE_INTERNAL_DATA_IN_STRING-sizeof(etk::Vector<char>)]; //!< Reserve the memory to have all time a buffer of N byte to remove un-needed allocation
|
||||
static const size_t m_sizeLocal;
|
||||
#endif
|
||||
public:
|
||||
static const size_t npos = size_t(-1);
|
||||
/**
|
||||
@ -314,25 +323,19 @@ namespace etk {
|
||||
* @param[in] _pos Desired position read
|
||||
* @return Reference on the Element
|
||||
*/
|
||||
char& get(size_t _pos) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
char& get(size_t _pos);
|
||||
/**
|
||||
* @brief Get an copy Element an a special position
|
||||
* @param[in] _pos Position in the string that might be get [0..Size()]
|
||||
* @return An reference on the copy of selected element
|
||||
*/
|
||||
char& operator[] (size_t _pos) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
char& operator[] (size_t _pos);
|
||||
/**
|
||||
* @brief Get an Element an a special position
|
||||
* @param[in] _pos Position in the string that might be get [0..Size()]
|
||||
* @return An reference on the selected element
|
||||
*/
|
||||
const char& operator[] (size_t _pos) const {
|
||||
return m_data[_pos];
|
||||
}
|
||||
const char& operator[] (size_t _pos) const;
|
||||
/**
|
||||
* @brief Add at the First position of the String
|
||||
* @param[in] _item Element to add at the end of string
|
||||
|
@ -48,7 +48,7 @@ namespace etk {
|
||||
*/
|
||||
template<class ETK_VECTOR_TYPE> class Vector {
|
||||
public:
|
||||
static const size_t npos = size_t(-1);
|
||||
//static const size_t npos = size_t(-1);
|
||||
class Iterator {
|
||||
private:
|
||||
size_t m_current; //!< current Id on the vector
|
||||
@ -241,7 +241,7 @@ namespace etk {
|
||||
changeAllocation(_count);
|
||||
// instanciate all objects
|
||||
for (size_t iii=0; iii<_count; ++iii) {
|
||||
new ((char*)&m_data[iii]) ETK_VECTOR_TYPE();
|
||||
new ((char*)&m_data[iii]) ETK_VECTOR_TYPE();
|
||||
}
|
||||
m_size = _count;
|
||||
}
|
||||
@ -299,7 +299,7 @@ namespace etk {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
delete[] (char*)m_data;
|
||||
ETK_FREE(char, m_data);
|
||||
m_data = nullptr;
|
||||
}
|
||||
m_allocated = 0;
|
||||
@ -825,7 +825,7 @@ namespace etk {
|
||||
// check if something is allocated :
|
||||
if (m_data == nullptr) {
|
||||
// no data allocated ==> request an allocation (might be the first)
|
||||
m_data = (ETK_VECTOR_TYPE*)(new char[sizeof(ETK_VECTOR_TYPE)*requestSize]);
|
||||
m_data = (ETK_VECTOR_TYPE*)ETK_MALLOC(char, sizeof(ETK_VECTOR_TYPE)*requestSize);
|
||||
if (m_data == nullptr) {
|
||||
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
||||
m_allocated = 0;
|
||||
@ -840,7 +840,7 @@ namespace etk {
|
||||
#endif
|
||||
} else {
|
||||
// allocate a new pool of data:
|
||||
ETK_VECTOR_TYPE* dataTmp = (ETK_VECTOR_TYPE*)(new char[sizeof(ETK_VECTOR_TYPE)*requestSize]);
|
||||
ETK_VECTOR_TYPE* dataTmp = (ETK_VECTOR_TYPE*)ETK_MALLOC(char, sizeof(ETK_VECTOR_TYPE)*requestSize);;
|
||||
if (dataTmp == nullptr) {
|
||||
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
||||
return;
|
||||
@ -872,7 +872,7 @@ namespace etk {
|
||||
m_data = dataTmp;
|
||||
// remove old pool
|
||||
if (dataTmp2 != nullptr) {
|
||||
delete[] (char*)dataTmp2;
|
||||
ETK_FREE(char, dataTmp2);
|
||||
}
|
||||
}
|
||||
// set the new allocation size
|
||||
|
@ -68,7 +68,7 @@ etk::Archive* etk::Archive::load(const etk::String& _fileName) {
|
||||
// select the corect Loader :
|
||||
if( tmpName.endWith(".zip") == true
|
||||
|| tmpName.endWith(".apk") == true ) {
|
||||
output = new etk::archive::Zip(_fileName);
|
||||
output = ETK_NEW(etk::archive::Zip, _fileName);
|
||||
if (output == nullptr) {
|
||||
TK_ERROR("An error occured when load archive : " << _fileName);
|
||||
}
|
||||
@ -104,7 +104,7 @@ etk::Archive* etk::Archive::loadPackage(const etk::String& _fileName) {
|
||||
}
|
||||
fclose(file);
|
||||
file = nullptr;
|
||||
output = new etk::archive::Zip(_fileName, position);
|
||||
output = ETK_NEW(etk::archive::Zip, _fileName, position);
|
||||
if (nullptr==output) {
|
||||
TK_ERROR("An error occured when load archive : " << _fileName);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <elog/elog.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <etk/typeInfo.hpp>
|
||||
#include <etk/Allocator.hpp>
|
||||
|
||||
static int32_t nbTimeInit = 0;
|
||||
|
||||
@ -27,6 +28,7 @@ void etk::unInit() {
|
||||
return;
|
||||
}
|
||||
TK_INFO("ETK system un-init (BEGIN)");
|
||||
ETK_MEM_SHOW_LOG();
|
||||
TK_INFO("ETK system un-init (END)");
|
||||
}
|
||||
|
||||
|
@ -1562,7 +1562,7 @@ etk::Vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
|
||||
if (m_systemFileName.size() == 0) {
|
||||
etk::Vector<etk::String> listDrive = getListDrive();
|
||||
for (auto &it : listDrive) {
|
||||
tmpp.pushBack(new etk::FSNode(it));
|
||||
tmpp.pushBack(ETK_NEW(etk::FSNode, it));
|
||||
}
|
||||
return tmpp;
|
||||
}
|
||||
@ -1607,8 +1607,8 @@ etk::Vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
|
||||
}
|
||||
if (findIt == false) {
|
||||
listAdded.pushBack(tmpString);
|
||||
tmpEmement = new etk::FSNode(tmpString);
|
||||
if (nullptr == tmpEmement) {
|
||||
tmpEmement = ETK_NEW(etk::FSNode, tmpString);
|
||||
if (tmpEmement == nullptr) {
|
||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||
continue;
|
||||
}
|
||||
@ -1634,24 +1634,24 @@ etk::Vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
|
||||
// do nothing ...
|
||||
continue;
|
||||
}
|
||||
if( false == start_with(tmpName, ".")
|
||||
|| true == _showHidenFile) {
|
||||
tmpEmement = new etk::FSNode(getRelativeFolder()+tmpName);
|
||||
if (nullptr == tmpEmement) {
|
||||
if( start_with(tmpName, ".") == false
|
||||
|| _showHidenFile == true) {
|
||||
tmpEmement = ETK_NEW(etk::FSNode, getRelativeFolder()+tmpName);
|
||||
if (tmpEmement == nullptr) {
|
||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||
continue;
|
||||
}
|
||||
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
||||
if (true == _getFile) {
|
||||
if (_getFile == true) {
|
||||
tmpp.pushBack(tmpEmement);
|
||||
} else {
|
||||
delete(tmpEmement);
|
||||
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||
tmpEmement = nullptr;
|
||||
}
|
||||
} else if (_getFolderAndOther) {
|
||||
tmpp.pushBack(tmpEmement);
|
||||
} else {
|
||||
delete(tmpEmement);
|
||||
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||
tmpEmement = nullptr;
|
||||
}
|
||||
}
|
||||
@ -1803,18 +1803,18 @@ void etk::FSNode::folderGetRecursiveFiles(etk::Vector<etk::String>& _output, boo
|
||||
continue;
|
||||
}
|
||||
//TK_DEBUG(" find : " << ent->d_name << " ==> " << (GetRelativeFolder()+tmpName));
|
||||
tmpEmement = new etk::FSNode(getRelativeFolder()+tmpName);
|
||||
if (nullptr != tmpEmement) {
|
||||
tmpEmement = ETK_NEW(etk::FSNode, getRelativeFolder()+tmpName);
|
||||
if (tmpEmement != nullptr) {
|
||||
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
||||
etk::String tmpVal = tmpEmement->getName();
|
||||
_output.pushBack(tmpVal);
|
||||
}
|
||||
if(tmpEmement->getNodeType() == etk::typeNode_folder) {
|
||||
if (true==_recursiveEnable) {
|
||||
if (_recursiveEnable == true) {
|
||||
tmpEmement->folderGetRecursiveFiles(_output, _recursiveEnable);
|
||||
}
|
||||
}
|
||||
delete(tmpEmement);
|
||||
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||
tmpEmement = nullptr;
|
||||
} else {
|
||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||
|
@ -28,7 +28,7 @@ namespace etk {
|
||||
/**
|
||||
* @brief Add an element declared type in the system database.
|
||||
* @param[in] Name of the type
|
||||
* @return The Id of the Object (new unique ID)
|
||||
* @return The Id of the Object (create a unique ID)
|
||||
*/
|
||||
size_t addType(const char* _name);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user