This commit is contained in:
IlushaShurupov 2023-07-15 10:29:51 +03:00 committed by Ilya Shurupov
parent b7560534c1
commit f46ea7e0fb
7 changed files with 145 additions and 155 deletions

View file

@ -14,6 +14,7 @@
* 2) updating list entry to that block.
*/
#include "HeapAllocatorGlobal.hpp"
#include "Environment.hpp"
#include "PrivateConfig.hpp"

View file

@ -1,6 +1,7 @@
#pragma once
#include "Utils.hpp"
#include "Buffer.hpp"
namespace tp {

View file

@ -2,162 +2,160 @@
#include "PoolAllocator.hpp"
#include "StringLogic.hpp"
#include "Buffer.hpp"
namespace tp {
// Static data
extern ModuleManifest gModuleStrings;
template<typename tChar>
class StringTemplate;
using String = StringTemplate<int1>;
template<typename tChar> class StringTemplate;
// Hidden slave class
template<typename tChar = int1>
class StringData {
friend StringTemplate<tChar>;
typedef StringLogic<tChar> Logic;
private:
uint2 mIsConst; // source is non-modifiable
uint2 mEditedIdx; // editor id
uint4 mReferenceCount; // number of users of this
tChar* mBuff; // actual string data
StringData() {
mBuff = (tChar*) "*";
mReferenceCount = 0;
mIsConst = true;
mEditedIdx = 0;
}
StringData(const tChar* aBuff, bool aIsConst) {
MODULE_SANITY_CHECK(gModuleStrings)
DEBUG_ASSERT(aBuff)
mBuff = (tChar*) aBuff;
mReferenceCount = 0;
mIsConst = aIsConst;
mEditedIdx = 0;
}
explicit StringData(const tChar* aBuff) {
MODULE_SANITY_CHECK(gModuleStrings)
DEBUG_ASSERT(aBuff)
auto const len = Logic::calcLength(aBuff);
resize(len);
memCopy(mBuff, aBuff, len);
mReferenceCount = 0;
mIsConst = false;
mEditedIdx = 0;
}
[[nodiscard]] tChar* getBuffer() {
return mBuff;
}
~StringData() {
if (!mIsConst) delete[] mBuff;
}
void resize(ualni size) {
DEBUG_ASSERT(mReferenceCount == 1 && !mIsConst)
delete[] mBuff;
mBuff = new tChar[size + 1];
mBuff[size] = Logic::getEndChar();
}
};
template<typename tChar = int1>
class StringTemplate {
public:
typedef StringLogic<tChar> Logic;
typedef Logic::Index Index;
typedef StringData<tChar> Data;
typedef typename Logic::Index Index;
private:
// Hidden slave class
class StringData {
public:
uint2 mIsConst; // source is non-modifiable
uint2 mEditedIdx; // editor id
uint4 mReferenceCount; // number of users of this
tChar* mBuff; // actual string data
StringData() {
MODULE_SANITY_CHECK(gModuleStrings)
mBuff = (tChar*) "*";
mReferenceCount = 0;
mIsConst = true;
mEditedIdx = 0;
}
StringData(const tChar* aBuff, bool aIsConst) {
MODULE_SANITY_CHECK(gModuleStrings)
DEBUG_ASSERT(aBuff)
mBuff = (tChar*) aBuff;
mReferenceCount = 0;
mIsConst = aIsConst;
mEditedIdx = 0;
}
explicit StringData(const tChar* aBuff) {
MODULE_SANITY_CHECK(gModuleStrings)
DEBUG_ASSERT(aBuff)
auto const len = Logic::calcLength(aBuff);
resize(len);
memCopy(mBuff, aBuff, len);
mReferenceCount = 0;
mIsConst = false;
mEditedIdx = 0;
}
[[nodiscard]] tChar* getBuffer() {
return mBuff;
}
~StringData() {
if (!mIsConst) delete[] mBuff;
}
void resize(ualni size) {
DEBUG_ASSERT(mReferenceCount == 1 && !mIsConst)
delete[] mBuff;
mBuff = new tChar[size + 1];
mBuff[size] = Logic::getEndChar();
}
};
private:
class StringData* mStringData;
private:
enum { STRINGS_POOL_SIZE = 1024, };
static PoolAlloc<StringData, STRINGS_POOL_SIZE>* sStringPool;
static StringData sNullString;
static PoolAlloc<StringData<tChar>, STRINGS_POOL_SIZE>* sStringPool;
static Data sNullString;
// --------------------------------- Main Interface ---------------------------------//
public:
private:
Data* mData;
public: // Main Interface
// Creates null string reference
StringTemplate() {
mStringData = &sNullString;
incReference(mStringData);
mData = &sNullString;
incReference(mData);
}
// References existing string data
StringTemplate(const StringTemplate& in) {
mStringData = in.mStringData;
incReference(mStringData);
mData = in.mData;
incReference(mData);
}
// Creates new string data from raw data pointer.
// Does not own string buffer - string buffer will not be freed. Initializes as const memory.
explicit StringTemplate(const tChar* raw) {
mStringData = new (sStringPool->allocate(0)) StringData(raw, true);
incReference(mStringData);
mData = new (sStringPool->allocate(0)) StringData(raw, true);
incReference(mData);
}
// Copies raw data and claims ownership over it
explicit StringTemplate(tChar* raw) {
mStringData = new (sStringPool->allocate(0)) StringData(raw);
incReference(mStringData);
mData = new (sStringPool->allocate(0)) StringData(raw);
incReference(mData);
}
~StringTemplate() {
decReference(mStringData);
decReference(mData);
}
private:
static void incReference(StringData* dp) {
static void incReference(Data* dp) {
dp->mReferenceCount++;
}
void decReference(StringData* dp) {
void decReference(Data* dp) {
dp->mReferenceCount--;
if (!dp->mReferenceCount) {
sStringPool->deallocate(mStringData);
mStringData->~StringData();
sStringPool->deallocate(mData);
mData->~StringData();
}
}
public: // Access
// used to read data
[[nodiscard]] const tChar* read() const {
return mStringData->mBuff;
return mData->mBuff;
}
// used to write data
// output will be null if in TextEditing mode
[[nodiscard]] tChar* write() {
makeModifiable();
return mStringData->getBuffer();
return mData->getBuffer();
}
// output will be null if in TextEditing mode
[[nodiscard]] tChar* resize() {
if (!mStringData->getEditor()) mStringData->resize();
return mStringData->getBuffer();
if (!mData->getEditor()) mData->resize();
return mData->getBuffer();
}
public:
void makeModifiable() {
// We have no rights to modify if someone references that memory too
// So we need to create new copy of StringData
if (mStringData->mReferenceCount > 1) {
mStringData = new (sStringPool->allocate(0)) StringData(mStringData->mBuff);
incReference(mStringData);
if (mData->mReferenceCount > 1) {
mData = new (sStringPool->allocate(0)) StringData(mData->mBuff);
incReference(mData);
return;
}
// Also if initial raw data was marked as const - create copy of raw data
// Note - raw data will be lost at this point if no other record of such is stored
if (mStringData->mIsConst) {
mStringData = new (sStringPool->allocate(0)) StringData(mStringData->mBuff);
incReference(mStringData);
if (mData->mIsConst) {
mData = new (sStringPool->allocate(0)) StringData(mData->mBuff);
incReference(mData);
}
}
@ -183,4 +181,12 @@ namespace tp {
return *this;
}
};
template<typename tChar>
PoolAlloc<StringData<tChar>, StringTemplate<tChar>::STRINGS_POOL_SIZE>* StringTemplate<tChar>::sStringPool;
template<typename tChar>
StringData<tChar> StringTemplate<tChar>::sNullString;
using String = StringTemplate<int1>;
}

21
Strings/tests/Tests.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "Testing.hpp"
#include "Strings.hpp"
void testStrings();
void testLogging();
int main() {
tp::ModuleManifest* deps[] = { &tp::gModuleStrings, &tp::gModuleUtils, nullptr };
tp::ModuleManifest testModule("StringsTest", nullptr, nullptr, deps);
if (!testModule.initialize()) {
return 1;
}
testStrings();
testLogging();
testModule.deinitialize();
}

View file

@ -0,0 +1,11 @@
#include "Testing.hpp"
#include "Logging.hpp"
TEST_DEF_STATIC(Simple) {
TEST(false);
}
TEST_DEF(Logging) {
testSimple();
}

View file

@ -0,0 +1,16 @@
#include "Testing.hpp"
#include "Strings.hpp"
TEST_DEF_STATIC(StringLogic) {
TEST(false);
}
TEST_DEF_STATIC(Simple) {
TEST(false);
}
TEST_DEF(Strings) {
testStringLogic();
testSimple();
}

View file

@ -1,66 +0,0 @@
#include "common.h"
#include "allocators.h"
#include "strings.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include "TextEditor.hpp"
#include "Logging.hpp"
using namespace tp;
void test_conversions() {
for (auto i : tp::Range(1000)) {
auto sign = bool(std::rand() % 2) ? 1 : -1;
auto floating = std::rand() / (tp::alnf)std::rand() * sign;
auto tmp = std::to_string(floating);
auto left = tp::string(tmp.c_str());
auto right = tp::string(floating);
DBG_BREAK(left != right);
auto back = (tp::alnf)right;
//DBG_BREAK(back != floating);
auto integer = std::rand() * sign;
tmp = std::to_string(integer);
left = tp::string(tmp.c_str());
right = tp::string(integer);
DBG_BREAK(left != right);
back = (tp::alni)right;
DBG_BREAK(back != integer);
}
}
void test_editor() {
tp::string str = " initial ";
str.createEdited();
auto edited = str.getEdited();
edited->setCursor({0, 4});
edited->insert({"aaa", 3});
str.saveEdited();
str.clearEdited();
GLog->write(str, true);
}
int main() {
tp::alloc_init();
string::Initialize();
Logger::init();
//test_conversions();
test_editor();
Logger::deinit();
string::UnInitialize();
tp::alloc_uninit();
}