[DEV] add an allocator checker
This commit is contained in:
parent
2a02c0c0be
commit
49f30a03e0
@ -11,6 +11,7 @@
|
|||||||
#include <echrono/Steady.hpp>
|
#include <echrono/Steady.hpp>
|
||||||
#include <echrono/Duration.hpp>
|
#include <echrono/Duration.hpp>
|
||||||
#include <etk/os/FSNode.hpp>
|
#include <etk/os/FSNode.hpp>
|
||||||
|
#include <etk/Allocator.hpp>
|
||||||
|
|
||||||
static int32_t nbTimeInit = 0;
|
static int32_t nbTimeInit = 0;
|
||||||
|
|
||||||
@ -207,19 +208,31 @@ int32_t etest::runAllTest() {
|
|||||||
if (it->getTestGroup() != itGroup) {
|
if (it->getTestGroup() != itGroup) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ETEST_PRINT("[ RUN ] " << itGroup << "." << it->getTestName());
|
#if ETK_MEMORY_CHECKER >= 0
|
||||||
it->clearLocal();
|
uint64_t* memorySnapShoot = etk::memory::createSnapshoot();
|
||||||
g_currentTest = it;
|
#endif
|
||||||
echrono::Steady ticTest = echrono::Steady::now();
|
{
|
||||||
it->run();
|
ETEST_PRINT("[ RUN ] " << itGroup << "." << it->getTestName());
|
||||||
echrono::Steady tocTest = echrono::Steady::now();
|
it->clearLocal();
|
||||||
g_currentTest = nullptr;
|
g_currentTest = it;
|
||||||
if (it->getError() == true) {
|
echrono::Steady ticTest = echrono::Steady::now();
|
||||||
ETEST_PRINT("[ FAIL ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
it->run();
|
||||||
errorCount++;
|
echrono::Steady tocTest = echrono::Steady::now();
|
||||||
} else {
|
g_currentTest = nullptr;
|
||||||
ETEST_PRINT("[ OK ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")");
|
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();
|
echrono::Steady tocGroup = echrono::Steady::now();
|
||||||
ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << " (" << (tocGroup - ticGroup) << ")");
|
ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << " (" << (tocGroup - ticGroup) << ")");
|
||||||
@ -229,6 +242,7 @@ int32_t etest::runAllTest() {
|
|||||||
if (errorCount != 0) {
|
if (errorCount != 0) {
|
||||||
ETEST_PRINT("[== FAIL ==] Have " << errorCount << " test fail");
|
ETEST_PRINT("[== FAIL ==] Have " << errorCount << " test fail");
|
||||||
}
|
}
|
||||||
|
ETK_MEM_SHOW_LOG();
|
||||||
return -errorCount;
|
return -errorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,8 @@ namespace etest {
|
|||||||
void run() override; \
|
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()
|
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
|
#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:
|
public:
|
||||||
FunctionPrivateLambda(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
FunctionPrivateLambda(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
||||||
m_dataPointer(_functor) {
|
m_dataPointer(_functor) {
|
||||||
ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
|
ETK_FUNCTION_DEBUG(" CREATE FunctionPrivateLambda \n");
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
FunctionPrivateLambda(const ETK_TYPE_FUNCTION_FUNCTOR& _functor):
|
FunctionPrivateLambda(const ETK_TYPE_FUNCTION_FUNCTOR& _functor):
|
||||||
m_dataPointer(_functor) {
|
m_dataPointer(_functor) {
|
||||||
ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n");
|
ETK_FUNCTION_DEBUG(" CREATE FunctionPrivateLambda \n");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
~FunctionPrivateLambda() {
|
~FunctionPrivateLambda() {
|
||||||
@ -56,7 +56,7 @@ namespace etk {
|
|||||||
}
|
}
|
||||||
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() {
|
FunctionPrivate<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)>* copy() {
|
||||||
ETK_FUNCTION_DEBUG(" COPY FunctionPrivateLambda \n");
|
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>
|
template <typename ETK_TYPE_FUNCTION_RETURN, typename... ETK_TYPE_FUNCTION_ARGS>
|
||||||
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
|
class Function<ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> {
|
||||||
private:
|
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;
|
uint32_t m_pppppp;
|
||||||
public:
|
public:
|
||||||
Function():
|
Function():
|
||||||
m_pointerPrivate(nullptr) {
|
m_pointerPrivate(nullptr) {
|
||||||
m_pppppp = MM___pppppp++;
|
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&):
|
Function(const etk::NullPtr&):
|
||||||
m_pointerPrivate(nullptr) {
|
m_pointerPrivate(nullptr) {
|
||||||
m_pppppp = MM___pppppp++;
|
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):
|
Function(const Function& _obj):
|
||||||
m_pointerPrivate(nullptr) {
|
m_pointerPrivate(nullptr) {
|
||||||
m_pppppp = MM___pppppp++;
|
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) {
|
if (_obj.m_pointerPrivate != nullptr) {
|
||||||
m_pointerPrivate = _obj.m_pointerPrivate->copy();
|
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):
|
Function(Function&& _obj):
|
||||||
m_pointerPrivate(nullptr) {
|
m_pointerPrivate(nullptr) {
|
||||||
m_pppppp = MM___pppppp++;
|
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);
|
_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,
|
template <typename ETK_TYPE_FUNCTION_FUNCTOR,
|
||||||
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
|
typename etk::EnableIf< !etk::IsSame<ETK_TYPE_FUNCTION_FUNCTOR,Function>::value
|
||||||
@ -104,13 +105,14 @@ namespace etk {
|
|||||||
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
Function(ETK_TYPE_FUNCTION_FUNCTOR _functor):
|
||||||
m_pointerPrivate(nullptr) {
|
m_pointerPrivate(nullptr) {
|
||||||
m_pppppp = MM___pppppp++;
|
m_pppppp = MM___pppppp++;
|
||||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 \n", m_pppppp, (uint64_t)this);
|
ETK_FUNCTION_DEBUG("[%d=0X%lx] create 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);
|
typedef FunctionPrivateLambda<ETK_TYPE_FUNCTION_FUNCTOR, ETK_TYPE_FUNCTION_RETURN(ETK_TYPE_FUNCTION_ARGS...)> FunctionPrivateLambdaTypedef;
|
||||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 (done)\n", m_pppppp, (uint64_t)this);
|
m_pointerPrivate = ETK_NEW(FunctionPrivateLambdaTypedef, _functor);
|
||||||
|
ETK_FUNCTION_DEBUG("[%d=0X%lx] create Function 4 (done)\n", m_pppppp, (uint64_t)this);
|
||||||
}
|
}
|
||||||
~Function() {
|
~Function() {
|
||||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] DELETE Function \n", m_pppppp, (uint64_t)this);
|
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;
|
m_pointerPrivate = nullptr;
|
||||||
}
|
}
|
||||||
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
|
ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const {
|
||||||
@ -134,7 +136,7 @@ namespace etk {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Function& operator= (etk::NullPtr _obj) {
|
Function& operator= (etk::NullPtr _obj) {
|
||||||
delete m_pointerPrivate;
|
ETK_DELETE(FunctionPrivateTypedef, m_pointerPrivate);
|
||||||
m_pointerPrivate = nullptr;
|
m_pointerPrivate = nullptr;
|
||||||
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = nullptr 0X%lx\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate);
|
ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = nullptr 0X%lx\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate);
|
||||||
return *this;
|
return *this;
|
||||||
|
18
etk/Map.hpp
18
etk/Map.hpp
@ -8,6 +8,7 @@
|
|||||||
#include <etk/types.hpp>
|
#include <etk/types.hpp>
|
||||||
#include <etk/Pair.hpp>
|
#include <etk/Pair.hpp>
|
||||||
#include <etk/Vector.hpp>
|
#include <etk/Vector.hpp>
|
||||||
|
#include <etk/Allocator.hpp>
|
||||||
|
|
||||||
namespace etk {
|
namespace etk {
|
||||||
/**
|
/**
|
||||||
@ -111,7 +112,7 @@ namespace etk {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Incremental operator
|
* @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 operator++ (int32_t) {
|
||||||
Iterator it(*this);
|
Iterator it(*this);
|
||||||
@ -120,7 +121,7 @@ namespace etk {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Decremental operator
|
* @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 operator-- (int32_t) {
|
||||||
Iterator it(*this);
|
Iterator it(*this);
|
||||||
@ -242,7 +243,8 @@ namespace etk {
|
|||||||
typedef bool (*sortFunction)(etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* const & _key1,
|
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);
|
etk::Pair<ETK_MAP_TYPE_KEY, ETK_MAP_TYPE_DATA>* const & _key2);
|
||||||
private:
|
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;
|
sortFunction m_comparator;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -296,7 +298,7 @@ namespace etk {
|
|||||||
if (it == nullptr) {
|
if (it == nullptr) {
|
||||||
continue;
|
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) {
|
void setOrdered(bool _ordered) {
|
||||||
@ -350,7 +352,7 @@ namespace etk {
|
|||||||
void clear() {
|
void clear() {
|
||||||
for (auto &it : m_data) {
|
for (auto &it : m_data) {
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
delete(it);
|
ETK_DELETE(pairType, it);
|
||||||
it=nullptr;
|
it=nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,7 +427,7 @@ namespace etk {
|
|||||||
void add(const ETK_MAP_TYPE_KEY& _key, const ETK_MAP_TYPE_DATA& _value) {
|
void add(const ETK_MAP_TYPE_KEY& _key, const ETK_MAP_TYPE_DATA& _value) {
|
||||||
int64_t elementId = getId(_key);
|
int64_t elementId = getId(_key);
|
||||||
if (elementId <0) {
|
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) {
|
if (tmp == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -457,7 +459,7 @@ namespace etk {
|
|||||||
//nothing to do ==> not existed
|
//nothing to do ==> not existed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delete(m_data[elementId]);
|
ETK_DELETE(pairType, m_data[elementId]);
|
||||||
m_data[elementId] = nullptr;
|
m_data[elementId] = nullptr;
|
||||||
m_data.erase(m_data.begin()+elementId);
|
m_data.erase(m_data.begin()+elementId);
|
||||||
}
|
}
|
||||||
@ -467,7 +469,7 @@ namespace etk {
|
|||||||
*/
|
*/
|
||||||
Iterator erase(const Iterator& _it) {
|
Iterator erase(const Iterator& _it) {
|
||||||
int64_t elementId = _it.m_current;
|
int64_t elementId = _it.m_current;
|
||||||
delete(m_data[elementId]);
|
ETK_DELETE(pairType, m_data[elementId]);
|
||||||
m_data[elementId] = nullptr;
|
m_data[elementId] = nullptr;
|
||||||
m_data.erase(m_data.begin()+elementId);
|
m_data.erase(m_data.begin()+elementId);
|
||||||
return position(elementId);
|
return position(elementId);
|
||||||
|
@ -792,7 +792,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
~NodePTheseElement() {
|
~NodePTheseElement() {
|
||||||
/*
|
/*
|
||||||
for (auto it : m_subNode) {
|
for (auto it : m_subNode) {
|
||||||
delete *it;
|
ETK_DELETE(Node<CLASS_TYPE>, *it);
|
||||||
*it = nullptr;
|
*it = nullptr;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -813,7 +813,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||||
}
|
}
|
||||||
// add to the under-node list :
|
// 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 ...
|
// move current position ...
|
||||||
pos += elementSize+1;
|
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]);
|
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||||
}
|
}
|
||||||
// add to the under-node list :
|
// 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 ...
|
// move current position ...
|
||||||
pos += elementSize+1;
|
pos += elementSize+1;
|
||||||
}
|
}
|
||||||
@ -869,7 +869,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
return false;
|
return false;
|
||||||
case regexOpcodeEOF:
|
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->setDescriptiveName("EOF");
|
||||||
tmpNode->addValue('\0');
|
tmpNode->addValue('\0');
|
||||||
tmpNode->setCountOutput(false);
|
tmpNode->setCountOutput(false);
|
||||||
@ -879,7 +879,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeDot:
|
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->setDescriptiveName("dot");
|
||||||
tmpNode->addValue('\0');
|
tmpNode->addValue('\0');
|
||||||
tmpNode->setInvert(true);
|
tmpNode->setInvert(true);
|
||||||
@ -887,11 +887,11 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case regexOpcodeStartOfLine:
|
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;
|
break;
|
||||||
case regexOpcodeEndOfLine:
|
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->setDescriptiveName("EOL");
|
||||||
tmpNode->addValue('\n');
|
tmpNode->addValue('\n');
|
||||||
m_subNode.pushBack(tmpNode);
|
m_subNode.pushBack(tmpNode);
|
||||||
@ -899,7 +899,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeDigit:
|
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->setDescriptiveName("digit");
|
||||||
tmpNode->addRange('0', '9');
|
tmpNode->addRange('0', '9');
|
||||||
m_subNode.pushBack(tmpNode);
|
m_subNode.pushBack(tmpNode);
|
||||||
@ -907,7 +907,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeDigitNot:
|
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->setDescriptiveName("digit-not");
|
||||||
tmpNode->addRange('0', '9');
|
tmpNode->addRange('0', '9');
|
||||||
tmpNode->setInvert(true);
|
tmpNode->setInvert(true);
|
||||||
@ -916,7 +916,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeLetter:
|
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->setDescriptiveName("letter");
|
||||||
tmpNode->addRange('a', 'z');
|
tmpNode->addRange('a', 'z');
|
||||||
tmpNode->addRange('A', 'Z');
|
tmpNode->addRange('A', 'Z');
|
||||||
@ -925,7 +925,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeLetterNot:
|
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->setDescriptiveName("letter-not");
|
||||||
tmpNode->addRange('a', 'z');
|
tmpNode->addRange('a', 'z');
|
||||||
tmpNode->addRange('A', 'Z');
|
tmpNode->addRange('A', 'Z');
|
||||||
@ -935,7 +935,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeSpace:
|
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->setDescriptiveName("space");
|
||||||
tmpNode->addValue(' ');
|
tmpNode->addValue(' ');
|
||||||
tmpNode->addValue('\t');
|
tmpNode->addValue('\t');
|
||||||
@ -948,7 +948,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeSpaceNot:
|
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->setDescriptiveName("space-not");
|
||||||
tmpNode->addValue(' ');
|
tmpNode->addValue(' ');
|
||||||
tmpNode->addValue('\t');
|
tmpNode->addValue('\t');
|
||||||
@ -962,7 +962,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeWord:
|
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->setDescriptiveName("word");
|
||||||
tmpNode->addRange('a', 'z');
|
tmpNode->addRange('a', 'z');
|
||||||
tmpNode->addRange('A', 'Z');
|
tmpNode->addRange('A', 'Z');
|
||||||
@ -972,7 +972,7 @@ template<class CLASS_TYPE> class NodePTheseElement : public Node<CLASS_TYPE> {
|
|||||||
break;
|
break;
|
||||||
case regexOpcodeWordNot:
|
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->setDescriptiveName("word-not");
|
||||||
tmpNode->addRange('a', 'z');
|
tmpNode->addRange('a', 'z');
|
||||||
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]);
|
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||||
}
|
}
|
||||||
// add to the under-node list :
|
// 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 ...
|
// move current position ...
|
||||||
pos += elementSize-1;
|
pos += elementSize-1;
|
||||||
}
|
}
|
||||||
@ -1142,7 +1142,7 @@ template<class CLASS_TYPE> class NodePThese : public Node<CLASS_TYPE> {
|
|||||||
~NodePThese() {
|
~NodePThese() {
|
||||||
/*
|
/*
|
||||||
for (auto it : m_subNode) {
|
for (auto it : m_subNode) {
|
||||||
delete *it;
|
ETK_DELETE(Node<CLASS_TYPE>, *it);
|
||||||
*it = nullptr;
|
*it = nullptr;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -1162,7 +1162,7 @@ template<class CLASS_TYPE> class NodePThese : public Node<CLASS_TYPE> {
|
|||||||
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
tmpData.pushBack(Node<CLASS_TYPE>::m_regExData[kkk]);
|
||||||
}
|
}
|
||||||
// add to the under-node list :
|
// 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;
|
pos += elementSize+1;
|
||||||
TK_REG_DEBUG("plop=" << createString(Node<CLASS_TYPE>::m_regExData, pos, pos+1) );
|
TK_REG_DEBUG("plop=" << createString(Node<CLASS_TYPE>::m_regExData, pos, pos+1) );
|
||||||
elementSize = getLenOfPTheseElement(Node<CLASS_TYPE>::m_regExData, pos);
|
elementSize = getLenOfPTheseElement(Node<CLASS_TYPE>::m_regExData, pos);
|
||||||
@ -1434,8 +1434,8 @@ template<class CLASS_TYPE> class RegEx {
|
|||||||
m_maximize = _value;
|
m_maximize = _value;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Set a new regular expression matching
|
* @brief Set a regular expression matching
|
||||||
* @param[in] _expression the new expression to search
|
* @param[in] _expression the expression to search
|
||||||
*/
|
*/
|
||||||
// TODO : Add an error ...
|
// TODO : Add an error ...
|
||||||
void compile(const etk::String &_expression) {
|
void compile(const etk::String &_expression) {
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
#include <etk/String.hpp>
|
#include <etk/String.hpp>
|
||||||
|
|
||||||
etk::Stream::Stream(size_t _basicSize) :
|
etk::Stream::Stream(size_t _basicSize) :
|
||||||
m_data(new etk::String) {
|
m_data(ETK_NEW(etk::String)) {
|
||||||
|
m_data->reserve(_basicSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
etk::Stream::~Stream() {
|
etk::Stream::~Stream() {
|
||||||
delete m_data;
|
ETK_DELETE(etk::String, m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
115
etk/String.cpp
115
etk/String.cpp
@ -3,13 +3,41 @@
|
|||||||
#include <etk/String.hpp>
|
#include <etk/String.hpp>
|
||||||
#include <etk/UString.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():
|
etk::String::String():
|
||||||
m_data() {
|
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) {
|
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) {
|
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;
|
_size = etk::String::npos;
|
||||||
}
|
}
|
||||||
if (_size != etk::String::npos) {
|
if (_size != etk::String::npos) {
|
||||||
resize(_size);
|
#if ETK_ENABLE_INTERNAL_DATA_IN_STRING > 0
|
||||||
for (size_t iii=0; iii<_size; ++iii) {
|
if (_size < sizeof(m_localData)) {
|
||||||
m_data[iii] = _obj.m_data[_pos+iii];
|
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;
|
return;
|
||||||
}
|
}
|
||||||
resize(_obj.size()-_pos);
|
resize(_obj.size()-_pos);
|
||||||
@ -35,11 +78,16 @@ etk::String::String(const char* _obj) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t size = strlen(_obj);
|
uint32_t size = strlen(_obj);
|
||||||
|
/*if (size == 0) {
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
resize(size);
|
resize(size);
|
||||||
for (size_t iii=0; iii<size; ++iii) {
|
for (size_t iii=0; iii<size; ++iii) {
|
||||||
m_data[iii] = _obj[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) {
|
etk::String::String(const etk::String _obj) {
|
||||||
resize(_obj.size());
|
resize(_obj.size());
|
||||||
@ -161,7 +209,11 @@ etk::String& etk::String::operator+= (char _value) {
|
|||||||
// Return the current pointer
|
// Return the current pointer
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t etk::String::size() const {
|
size_t etk::String::size() const {
|
||||||
|
if (m_data.size() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return m_data.size() - 1; // remove '\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() {
|
void etk::String::popBack() {
|
||||||
if(size()>0) {
|
if(size() > 0) {
|
||||||
resize(size()-1);
|
resize(size()-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +261,7 @@ void etk::String::reserve(size_t _size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void etk::String::clear() {
|
void etk::String::clear() {
|
||||||
resize(0);
|
m_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void etk::String::insert(size_t _pos, const char* _item, size_t _nbElement) {
|
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) {
|
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());
|
//TK_ERROR(" can not Erase Element at this position : " << _pos << " > " << size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -278,7 +330,7 @@ void etk::String::eraseRange(size_t _pos, size_t _posEnd) {
|
|||||||
size_t tmpSize = size();
|
size_t tmpSize = size();
|
||||||
// move current data
|
// move current data
|
||||||
size_t sizeToMove = (tmpSize - (_pos+nbElement));
|
size_t sizeToMove = (tmpSize - (_pos+nbElement));
|
||||||
if ( 0 < sizeToMove) {
|
if (sizeToMove > 0) {
|
||||||
for (size_t iii=0; iii<sizeToMove; iii++) {
|
for (size_t iii=0; iii<sizeToMove; iii++) {
|
||||||
m_data[_pos+iii] = m_data[_pos+nbElement+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 etk::String::extract(size_t _posStart, size_t _posEnd) const {
|
||||||
etk::String out;
|
etk::String out;
|
||||||
if (_posStart >= size() ) {
|
if (_posStart >= size()) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
if (_posEnd >= size() ) {
|
if (_posEnd >= size()) {
|
||||||
_posEnd = size();
|
_posEnd = size();
|
||||||
}
|
}
|
||||||
out.pushBack(&m_data[_posStart], _posEnd-_posStart);
|
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 {
|
const char* etk::String::c_str() const {
|
||||||
|
if (m_data.size() == 0) {
|
||||||
|
return getStaticEmptyString();
|
||||||
|
}
|
||||||
return &m_data[0];
|
return &m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,14 +375,18 @@ const etk::String::Iterator etk::String::begin() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
etk::String::Iterator etk::String::end() {
|
etk::String::Iterator etk::String::end() {
|
||||||
return position( size() );
|
return position(size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const etk::String::Iterator etk::String::end() const {
|
const etk::String::Iterator etk::String::end() const {
|
||||||
return position( size() );
|
return position(size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void etk::String::resize(size_t _newSize, char _value) {
|
void etk::String::resize(size_t _newSize, char _value) {
|
||||||
|
if (_newSize == 0) {
|
||||||
|
m_data.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
size_t oldSize = m_data.size();
|
size_t oldSize = m_data.size();
|
||||||
if (oldSize != 0) {
|
if (oldSize != 0) {
|
||||||
m_data[m_data.size()-1] = _value;
|
m_data[m_data.size()-1] = _value;
|
||||||
@ -342,7 +401,7 @@ bool etk::String::operator== (const etk::String& _obj) const {
|
|||||||
if( this == &_obj ) {
|
if( this == &_obj ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// first step : check the size ...
|
// first step: check the size...
|
||||||
if (m_data.size() != _obj.m_data.size()) {
|
if (m_data.size() != _obj.m_data.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -359,7 +418,7 @@ bool etk::String::operator!= (const etk::String& _obj) const {
|
|||||||
if( this == &_obj ) {
|
if( this == &_obj ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// first step : check the size ...
|
// first step: check the size...
|
||||||
if (m_data.size() != _obj.m_data.size()) {
|
if (m_data.size() != _obj.m_data.size()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -371,6 +430,26 @@ bool etk::String::operator!= (const etk::String& _obj) const {
|
|||||||
return false;
|
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) {
|
char etk::toLower(char _value) {
|
||||||
if ( _value >= 'A'
|
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 etk::toHex(uint64_t _value, uint32_t _size) {
|
||||||
etk::String out;
|
etk::String out;
|
||||||
for (int32_t iii = 15; iii >=0; --iii) {
|
for (int32_t iii = 15; iii >=0; --iii) {
|
||||||
if ( _size >= iii
|
if ( _size >= uint64_t(iii)
|
||||||
|| _value >= uint64_t(1)<<iii) {
|
|| _value >= uint64_t(1)<<iii) {
|
||||||
out += etk::toHexChar((_value>>(iii*4)) & 0x0F);
|
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 etk::toBin(uint64_t _value, uint32_t _size) {
|
||||||
etk::String out;
|
etk::String out;
|
||||||
for (int32_t iii = 63; iii >=0; --iii) {
|
for (int32_t iii = 63; iii >=0; --iii) {
|
||||||
if ( _size >= iii
|
if ( _size >= uint64_t(iii)
|
||||||
|| _value >= uint64_t(1)<<iii) {
|
|| _value >= uint64_t(1)<<iii) {
|
||||||
out += etk::toHexChar((_value>>(iii)) & 0x01);
|
out += etk::toHexChar((_value>>(iii)) & 0x01);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
//#include <etk/debug.hpp>
|
//#include <etk/debug.hpp>
|
||||||
#include <etk/Vector.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 {
|
namespace etk {
|
||||||
/**
|
/**
|
||||||
@ -19,7 +24,7 @@ namespace etk {
|
|||||||
class Iterator {
|
class Iterator {
|
||||||
private:
|
private:
|
||||||
size_t m_current; //!< current Id on the string
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Basic iterator constructor with no link with an etk::String
|
* @brief Basic iterator constructor with no link with an etk::String
|
||||||
@ -201,6 +206,10 @@ namespace etk {
|
|||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
etk::Vector<char> m_data; //!< pointer on the current data (contain all time 1 element '\0')
|
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:
|
public:
|
||||||
static const size_t npos = size_t(-1);
|
static const size_t npos = size_t(-1);
|
||||||
/**
|
/**
|
||||||
@ -314,25 +323,19 @@ namespace etk {
|
|||||||
* @param[in] _pos Desired position read
|
* @param[in] _pos Desired position read
|
||||||
* @return Reference on the Element
|
* @return Reference on the Element
|
||||||
*/
|
*/
|
||||||
char& get(size_t _pos) {
|
char& get(size_t _pos);
|
||||||
return m_data[_pos];
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @brief Get an copy Element an a special position
|
* @brief Get an copy Element an a special position
|
||||||
* @param[in] _pos Position in the string that might be get [0..Size()]
|
* @param[in] _pos Position in the string that might be get [0..Size()]
|
||||||
* @return An reference on the copy of selected element
|
* @return An reference on the copy of selected element
|
||||||
*/
|
*/
|
||||||
char& operator[] (size_t _pos) {
|
char& operator[] (size_t _pos);
|
||||||
return m_data[_pos];
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @brief Get an Element an a special position
|
* @brief Get an Element an a special position
|
||||||
* @param[in] _pos Position in the string that might be get [0..Size()]
|
* @param[in] _pos Position in the string that might be get [0..Size()]
|
||||||
* @return An reference on the selected element
|
* @return An reference on the selected element
|
||||||
*/
|
*/
|
||||||
const char& operator[] (size_t _pos) const {
|
const char& operator[] (size_t _pos) const;
|
||||||
return m_data[_pos];
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @brief Add at the First position of the String
|
* @brief Add at the First position of the String
|
||||||
* @param[in] _item Element to add at the end of 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 {
|
template<class ETK_VECTOR_TYPE> class Vector {
|
||||||
public:
|
public:
|
||||||
static const size_t npos = size_t(-1);
|
//static const size_t npos = size_t(-1);
|
||||||
class Iterator {
|
class Iterator {
|
||||||
private:
|
private:
|
||||||
size_t m_current; //!< current Id on the vector
|
size_t m_current; //!< current Id on the vector
|
||||||
@ -241,7 +241,7 @@ namespace etk {
|
|||||||
changeAllocation(_count);
|
changeAllocation(_count);
|
||||||
// instanciate all objects
|
// instanciate all objects
|
||||||
for (size_t iii=0; iii<_count; ++iii) {
|
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;
|
m_size = _count;
|
||||||
}
|
}
|
||||||
@ -299,7 +299,7 @@ namespace etk {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
delete[] (char*)m_data;
|
ETK_FREE(char, m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
m_allocated = 0;
|
m_allocated = 0;
|
||||||
@ -825,7 +825,7 @@ namespace etk {
|
|||||||
// check if something is allocated :
|
// check if something is allocated :
|
||||||
if (m_data == nullptr) {
|
if (m_data == nullptr) {
|
||||||
// no data allocated ==> request an allocation (might be the first)
|
// 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) {
|
if (m_data == nullptr) {
|
||||||
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
||||||
m_allocated = 0;
|
m_allocated = 0;
|
||||||
@ -840,7 +840,7 @@ namespace etk {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// allocate a new pool of data:
|
// 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) {
|
if (dataTmp == nullptr) {
|
||||||
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
//TK_CRITICAL("Vector : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_VECTOR_TYPE)) << "bytes" );
|
||||||
return;
|
return;
|
||||||
@ -872,7 +872,7 @@ namespace etk {
|
|||||||
m_data = dataTmp;
|
m_data = dataTmp;
|
||||||
// remove old pool
|
// remove old pool
|
||||||
if (dataTmp2 != nullptr) {
|
if (dataTmp2 != nullptr) {
|
||||||
delete[] (char*)dataTmp2;
|
ETK_FREE(char, dataTmp2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set the new allocation size
|
// set the new allocation size
|
||||||
|
@ -68,7 +68,7 @@ etk::Archive* etk::Archive::load(const etk::String& _fileName) {
|
|||||||
// select the corect Loader :
|
// select the corect Loader :
|
||||||
if( tmpName.endWith(".zip") == true
|
if( tmpName.endWith(".zip") == true
|
||||||
|| tmpName.endWith(".apk") == true ) {
|
|| tmpName.endWith(".apk") == true ) {
|
||||||
output = new etk::archive::Zip(_fileName);
|
output = ETK_NEW(etk::archive::Zip, _fileName);
|
||||||
if (output == nullptr) {
|
if (output == nullptr) {
|
||||||
TK_ERROR("An error occured when load archive : " << _fileName);
|
TK_ERROR("An error occured when load archive : " << _fileName);
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ etk::Archive* etk::Archive::loadPackage(const etk::String& _fileName) {
|
|||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
file = nullptr;
|
file = nullptr;
|
||||||
output = new etk::archive::Zip(_fileName, position);
|
output = ETK_NEW(etk::archive::Zip, _fileName, position);
|
||||||
if (nullptr==output) {
|
if (nullptr==output) {
|
||||||
TK_ERROR("An error occured when load archive : " << _fileName);
|
TK_ERROR("An error occured when load archive : " << _fileName);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <elog/elog.hpp>
|
#include <elog/elog.hpp>
|
||||||
#include <etk/os/FSNode.hpp>
|
#include <etk/os/FSNode.hpp>
|
||||||
#include <etk/typeInfo.hpp>
|
#include <etk/typeInfo.hpp>
|
||||||
|
#include <etk/Allocator.hpp>
|
||||||
|
|
||||||
static int32_t nbTimeInit = 0;
|
static int32_t nbTimeInit = 0;
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ void etk::unInit() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TK_INFO("ETK system un-init (BEGIN)");
|
TK_INFO("ETK system un-init (BEGIN)");
|
||||||
|
ETK_MEM_SHOW_LOG();
|
||||||
TK_INFO("ETK system un-init (END)");
|
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) {
|
if (m_systemFileName.size() == 0) {
|
||||||
etk::Vector<etk::String> listDrive = getListDrive();
|
etk::Vector<etk::String> listDrive = getListDrive();
|
||||||
for (auto &it : listDrive) {
|
for (auto &it : listDrive) {
|
||||||
tmpp.pushBack(new etk::FSNode(it));
|
tmpp.pushBack(ETK_NEW(etk::FSNode, it));
|
||||||
}
|
}
|
||||||
return tmpp;
|
return tmpp;
|
||||||
}
|
}
|
||||||
@ -1607,8 +1607,8 @@ etk::Vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
|
|||||||
}
|
}
|
||||||
if (findIt == false) {
|
if (findIt == false) {
|
||||||
listAdded.pushBack(tmpString);
|
listAdded.pushBack(tmpString);
|
||||||
tmpEmement = new etk::FSNode(tmpString);
|
tmpEmement = ETK_NEW(etk::FSNode, tmpString);
|
||||||
if (nullptr == tmpEmement) {
|
if (tmpEmement == nullptr) {
|
||||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1634,24 +1634,24 @@ etk::Vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
|
|||||||
// do nothing ...
|
// do nothing ...
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( false == start_with(tmpName, ".")
|
if( start_with(tmpName, ".") == false
|
||||||
|| true == _showHidenFile) {
|
|| _showHidenFile == true) {
|
||||||
tmpEmement = new etk::FSNode(getRelativeFolder()+tmpName);
|
tmpEmement = ETK_NEW(etk::FSNode, getRelativeFolder()+tmpName);
|
||||||
if (nullptr == tmpEmement) {
|
if (tmpEmement == nullptr) {
|
||||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
||||||
if (true == _getFile) {
|
if (_getFile == true) {
|
||||||
tmpp.pushBack(tmpEmement);
|
tmpp.pushBack(tmpEmement);
|
||||||
} else {
|
} else {
|
||||||
delete(tmpEmement);
|
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||||
tmpEmement = nullptr;
|
tmpEmement = nullptr;
|
||||||
}
|
}
|
||||||
} else if (_getFolderAndOther) {
|
} else if (_getFolderAndOther) {
|
||||||
tmpp.pushBack(tmpEmement);
|
tmpp.pushBack(tmpEmement);
|
||||||
} else {
|
} else {
|
||||||
delete(tmpEmement);
|
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||||
tmpEmement = nullptr;
|
tmpEmement = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1803,18 +1803,18 @@ void etk::FSNode::folderGetRecursiveFiles(etk::Vector<etk::String>& _output, boo
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//TK_DEBUG(" find : " << ent->d_name << " ==> " << (GetRelativeFolder()+tmpName));
|
//TK_DEBUG(" find : " << ent->d_name << " ==> " << (GetRelativeFolder()+tmpName));
|
||||||
tmpEmement = new etk::FSNode(getRelativeFolder()+tmpName);
|
tmpEmement = ETK_NEW(etk::FSNode, getRelativeFolder()+tmpName);
|
||||||
if (nullptr != tmpEmement) {
|
if (tmpEmement != nullptr) {
|
||||||
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
if(tmpEmement->getNodeType() == etk::typeNode_file) {
|
||||||
etk::String tmpVal = tmpEmement->getName();
|
etk::String tmpVal = tmpEmement->getName();
|
||||||
_output.pushBack(tmpVal);
|
_output.pushBack(tmpVal);
|
||||||
}
|
}
|
||||||
if(tmpEmement->getNodeType() == etk::typeNode_folder) {
|
if(tmpEmement->getNodeType() == etk::typeNode_folder) {
|
||||||
if (true==_recursiveEnable) {
|
if (_recursiveEnable == true) {
|
||||||
tmpEmement->folderGetRecursiveFiles(_output, _recursiveEnable);
|
tmpEmement->folderGetRecursiveFiles(_output, _recursiveEnable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(tmpEmement);
|
ETK_DELETE(etk::FSNode, tmpEmement);
|
||||||
tmpEmement = nullptr;
|
tmpEmement = nullptr;
|
||||||
} else {
|
} else {
|
||||||
TK_ERROR("allocation error ... of ewol::FSNode");
|
TK_ERROR("allocation error ... of ewol::FSNode");
|
||||||
|
@ -28,7 +28,7 @@ namespace etk {
|
|||||||
/**
|
/**
|
||||||
* @brief Add an element declared type in the system database.
|
* @brief Add an element declared type in the system database.
|
||||||
* @param[in] Name of the type
|
* @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);
|
size_t addType(const char* _name);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user