Apply formating to all files. CLeanup
This commit is contained in:
parent
b4ae5dde77
commit
91fb72bd49
928 changed files with 14515 additions and 21479 deletions
|
|
@ -1,59 +1,58 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Buffer.hpp"
|
||||
#include "List.hpp"
|
||||
#include "Strings.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
|
||||
class Report {
|
||||
String mData;
|
||||
Buffer<String::Index> mLineOffsets;
|
||||
|
||||
public:
|
||||
enum Type { INFO, ERR, WARN, SUC } mType = INFO;
|
||||
|
||||
public:
|
||||
Report();
|
||||
explicit Report(const String& text);
|
||||
Report(const String& text, Type type);
|
||||
|
||||
public:
|
||||
[[nodiscard]] ualni getLineCount() const;
|
||||
[[nodiscard]] String getString() const;
|
||||
|
||||
private:
|
||||
void calcLineCount();
|
||||
};
|
||||
|
||||
private:
|
||||
List<Report>::Node* mCursor = nullptr;
|
||||
List<Report> mBuff;
|
||||
ualni mLineCount = 0;
|
||||
|
||||
public:
|
||||
void write(const String& in, bool post = true, Report::Type type = Report::Type::INFO);
|
||||
|
||||
[[nodiscard]] String read();
|
||||
[[nodiscard]] const List<Report>& getBuff() const { return mBuff; }
|
||||
[[nodiscard]] ualni getLineCount() const { return mLineCount; }
|
||||
|
||||
public:
|
||||
static void initializeGlobal();
|
||||
static void deinitializeGlobal();
|
||||
};
|
||||
|
||||
extern Logger* gLogger;
|
||||
}
|
||||
|
||||
#define LOG(val) tp::str::gLogger->write((val), 1)
|
||||
|
||||
#ifdef ENV_BUILD_DEBUG
|
||||
#define DEBUG_LOG(val) tp::str::gLogger->write((val), 1)
|
||||
#else
|
||||
#define DEBUG_LOG(val) (0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Buffer.hpp"
|
||||
#include "List.hpp"
|
||||
#include "Strings.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
class Report {
|
||||
String mData;
|
||||
Buffer<String::Index> mLineOffsets;
|
||||
|
||||
public:
|
||||
enum Type { INFO, ERR, WARN, SUC } mType = INFO;
|
||||
|
||||
public:
|
||||
Report();
|
||||
explicit Report(const String& text);
|
||||
Report(const String& text, Type type);
|
||||
|
||||
public:
|
||||
[[nodiscard]] ualni getLineCount() const;
|
||||
[[nodiscard]] String getString() const;
|
||||
|
||||
private:
|
||||
void calcLineCount();
|
||||
};
|
||||
|
||||
private:
|
||||
List<Report>::Node* mCursor = nullptr;
|
||||
List<Report> mBuff;
|
||||
ualni mLineCount = 0;
|
||||
|
||||
public:
|
||||
void write(const String& in, bool post = true, Report::Type type = Report::Type::INFO);
|
||||
|
||||
[[nodiscard]] String read();
|
||||
[[nodiscard]] const List<Report>& getBuff() const { return mBuff; }
|
||||
[[nodiscard]] ualni getLineCount() const { return mLineCount; }
|
||||
|
||||
public:
|
||||
static void initializeGlobal();
|
||||
static void deinitializeGlobal();
|
||||
};
|
||||
|
||||
extern Logger* gLogger;
|
||||
}
|
||||
|
||||
#define LOG(val) tp::str::gLogger->write((val), 1)
|
||||
|
||||
#ifdef ENV_BUILD_DEBUG
|
||||
#define DEBUG_LOG(val) tp::str::gLogger->write((val), 1)
|
||||
#else
|
||||
#define DEBUG_LOG(val) (0)
|
||||
#endif
|
||||
|
|
@ -1,140 +1,138 @@
|
|||
#pragma once
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace tp {
|
||||
|
||||
template<typename tChar = uint1>
|
||||
class StringLogic {
|
||||
public:
|
||||
|
||||
typedef halni Index;
|
||||
typedef Index LineId;
|
||||
typedef Index ColumnId;
|
||||
|
||||
static inline bool isNewLineChar(tChar in) { return (in == '\n') || (in == '\r'); }
|
||||
static inline bool isEndChar(tChar in) { return in == '\0'; }
|
||||
static constexpr tChar getEndChar() { return '\0'; }
|
||||
|
||||
static Index calcLength(const tChar* in) {
|
||||
const tChar* iter = in;
|
||||
while (*iter != '\0') iter++;
|
||||
return iter - in;
|
||||
}
|
||||
|
||||
static void insertLogic(tChar* result, Index resultLen, const tChar* cur, const tChar* tar, Index at, Index len) {
|
||||
auto curLen = calcLength(cur);
|
||||
auto allLen = curLen + len;
|
||||
ASSERT(allLen <= resultLen);
|
||||
|
||||
DEBUG_ASSERT(curLen >= 0)
|
||||
DEBUG_ASSERT(len >= 0)
|
||||
DEBUG_ASSERT(at < curLen + 1 && at >= 0)
|
||||
|
||||
for (Index idx = 0; idx < at; idx++) {
|
||||
result[idx] = cur[idx];
|
||||
}
|
||||
for (Index idx = 0; idx < len; idx++) {
|
||||
result[idx + at] = tar[idx];
|
||||
}
|
||||
for (Index idx = at + len; idx < allLen; idx++) {
|
||||
result[idx] = cur[idx - len];
|
||||
}
|
||||
result[allLen] = '\0';
|
||||
}
|
||||
|
||||
// including end not including start
|
||||
static void removeLogic(tChar* result, Index resultLen, const tChar* cur, Index start, Index end) {
|
||||
auto curLen = calcLength(cur);
|
||||
auto rangeLen = end - start;
|
||||
auto newLen = curLen - rangeLen;
|
||||
|
||||
ASSERT(newLen <= resultLen);
|
||||
|
||||
result[newLen] = '\0';
|
||||
for (Index idx = 0; idx < start; idx++) {
|
||||
result[idx] = cur[idx];
|
||||
}
|
||||
for (Index idx = end; idx < curLen; idx++) {
|
||||
result[idx - rangeLen] = cur[idx];
|
||||
}
|
||||
}
|
||||
|
||||
static bool isEqualLogic(const tChar* left, const tChar* right) {
|
||||
Index idx = 0;
|
||||
LOOP:
|
||||
if (left[idx] == '\0' || right[idx] == '\0') {
|
||||
if (left[idx] == '\0' && right[idx] == '\0') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (left[idx] != right[idx]) {
|
||||
return false;
|
||||
}
|
||||
idx++;
|
||||
goto LOOP;
|
||||
}
|
||||
|
||||
// returns 0 : nl1 + 1 : nl2 + 1 : nl3 + 1 : ... : size
|
||||
static void calcLineOffsets(const tChar* aBuff, Index aLength, Buffer<Index>& aOut) {
|
||||
Index lines = 0;
|
||||
for (auto idx : Range(aLength)) {
|
||||
if (isNewLineChar(aBuff[idx])) {
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
aOut.reserve(lines + 2); // plus start and end offsets
|
||||
lines = 0;
|
||||
for (auto idx : Range(aLength)) {
|
||||
if (isNewLineChar(aBuff[idx])) {
|
||||
aOut[lines + 1] = Index(idx + 1);
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
aOut[0] = 0;
|
||||
aOut[lines + 1] = aLength;
|
||||
}
|
||||
|
||||
|
||||
static bool convertStringToValue(const tChar* input, alni& output) {
|
||||
char* endPtr;
|
||||
output = std::strtoll(input, &endPtr, 10);
|
||||
return (endPtr == input + calcLength(input));
|
||||
}
|
||||
|
||||
static bool convertStringToValue(const tChar* input, alnf& output) {
|
||||
char* endPtr;
|
||||
output = std::strtod(input, &endPtr);
|
||||
return (endPtr == input + calcLength(input));
|
||||
}
|
||||
|
||||
static bool convertStringToValue(const tChar* input, bool& output) {
|
||||
output = !(isEqualLogic(input, "False") || isEqualLogic(input, "false") || isEqualLogic(input, "0"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool convertValueToString(alni input, tChar* output, Index bufferSize) {
|
||||
int result = std::snprintf(output, bufferSize, "%lld", input);
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
static bool convertValueToString(alnf input, tChar* output, Index bufferSize) {
|
||||
int result = std::snprintf(output, bufferSize, "%f", input);
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
static bool convertValueToString(bool input, tChar* output, Index bufferSize) {
|
||||
const char* str = (input ? "true" : "false");
|
||||
Index length = calcLength(str);
|
||||
if (length >= bufferSize)
|
||||
return false;
|
||||
memCopy(output, str, length + 1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace tp {
|
||||
|
||||
template <typename tChar = uint1>
|
||||
class StringLogic {
|
||||
public:
|
||||
typedef halni Index;
|
||||
typedef Index LineId;
|
||||
typedef Index ColumnId;
|
||||
|
||||
static inline bool isNewLineChar(tChar in) { return (in == '\n') || (in == '\r'); }
|
||||
static inline bool isEndChar(tChar in) { return in == '\0'; }
|
||||
static constexpr tChar getEndChar() { return '\0'; }
|
||||
|
||||
static Index calcLength(const tChar* in) {
|
||||
const tChar* iter = in;
|
||||
while (*iter != '\0')
|
||||
iter++;
|
||||
return iter - in;
|
||||
}
|
||||
|
||||
static void insertLogic(tChar* result, Index resultLen, const tChar* cur, const tChar* tar, Index at, Index len) {
|
||||
auto curLen = calcLength(cur);
|
||||
auto allLen = curLen + len;
|
||||
ASSERT(allLen <= resultLen);
|
||||
|
||||
DEBUG_ASSERT(curLen >= 0)
|
||||
DEBUG_ASSERT(len >= 0)
|
||||
DEBUG_ASSERT(at < curLen + 1 && at >= 0)
|
||||
|
||||
for (Index idx = 0; idx < at; idx++) {
|
||||
result[idx] = cur[idx];
|
||||
}
|
||||
for (Index idx = 0; idx < len; idx++) {
|
||||
result[idx + at] = tar[idx];
|
||||
}
|
||||
for (Index idx = at + len; idx < allLen; idx++) {
|
||||
result[idx] = cur[idx - len];
|
||||
}
|
||||
result[allLen] = '\0';
|
||||
}
|
||||
|
||||
// including end not including start
|
||||
static void removeLogic(tChar* result, Index resultLen, const tChar* cur, Index start, Index end) {
|
||||
auto curLen = calcLength(cur);
|
||||
auto rangeLen = end - start;
|
||||
auto newLen = curLen - rangeLen;
|
||||
|
||||
ASSERT(newLen <= resultLen);
|
||||
|
||||
result[newLen] = '\0';
|
||||
for (Index idx = 0; idx < start; idx++) {
|
||||
result[idx] = cur[idx];
|
||||
}
|
||||
for (Index idx = end; idx < curLen; idx++) {
|
||||
result[idx - rangeLen] = cur[idx];
|
||||
}
|
||||
}
|
||||
|
||||
static bool isEqualLogic(const tChar* left, const tChar* right) {
|
||||
Index idx = 0;
|
||||
LOOP:
|
||||
if (left[idx] == '\0' || right[idx] == '\0') {
|
||||
if (left[idx] == '\0' && right[idx] == '\0') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (left[idx] != right[idx]) {
|
||||
return false;
|
||||
}
|
||||
idx++;
|
||||
goto LOOP;
|
||||
}
|
||||
|
||||
// returns 0 : nl1 + 1 : nl2 + 1 : nl3 + 1 : ... : size
|
||||
static void calcLineOffsets(const tChar* aBuff, Index aLength, Buffer<Index>& aOut) {
|
||||
Index lines = 0;
|
||||
for (auto idx : Range(aLength)) {
|
||||
if (isNewLineChar(aBuff[idx])) {
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
aOut.reserve(lines + 2); // plus start and end offsets
|
||||
lines = 0;
|
||||
for (auto idx : Range(aLength)) {
|
||||
if (isNewLineChar(aBuff[idx])) {
|
||||
aOut[lines + 1] = Index(idx + 1);
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
aOut[0] = 0;
|
||||
aOut[lines + 1] = aLength;
|
||||
}
|
||||
|
||||
static bool convertStringToValue(const tChar* input, alni& output) {
|
||||
char* endPtr;
|
||||
output = std::strtoll(input, &endPtr, 10);
|
||||
return (endPtr == input + calcLength(input));
|
||||
}
|
||||
|
||||
static bool convertStringToValue(const tChar* input, alnf& output) {
|
||||
char* endPtr;
|
||||
output = std::strtod(input, &endPtr);
|
||||
return (endPtr == input + calcLength(input));
|
||||
}
|
||||
|
||||
static bool convertStringToValue(const tChar* input, bool& output) {
|
||||
output = !(isEqualLogic(input, "False") || isEqualLogic(input, "false") || isEqualLogic(input, "0"));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool convertValueToString(alni input, tChar* output, Index bufferSize) {
|
||||
int result = std::snprintf(output, bufferSize, "%lld", input);
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
static bool convertValueToString(alnf input, tChar* output, Index bufferSize) {
|
||||
int result = std::snprintf(output, bufferSize, "%f", input);
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
static bool convertValueToString(bool input, tChar* output, Index bufferSize) {
|
||||
const char* str = (input ? "true" : "false");
|
||||
Index length = calcLength(str);
|
||||
if (length >= bufferSize) return false;
|
||||
memCopy(output, str, length + 1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,286 +1,273 @@
|
|||
#pragma once
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "StringLogic.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
// Static data
|
||||
extern ModuleManifest gModuleStrings;
|
||||
|
||||
template<typename tChar> class StringTemplate;
|
||||
|
||||
// Hidden slave class
|
||||
template<typename tChar = int1>
|
||||
class StringData {
|
||||
friend StringTemplate<tChar>;
|
||||
typedef StringLogic<tChar> Logic;
|
||||
typedef typename StringLogic<tChar>::Index Index;
|
||||
|
||||
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 = 1;
|
||||
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(tChar* aBuff) {
|
||||
MODULE_SANITY_CHECK(gModuleStrings)
|
||||
DEBUG_ASSERT(aBuff)
|
||||
auto const len = Logic::calcLength(aBuff);
|
||||
mReferenceCount = 0;
|
||||
mIsConst = false;
|
||||
mEditedIdx = 0;
|
||||
mBuff = new tChar[len + 1];
|
||||
mBuff[len] = Logic::getEndChar();
|
||||
memCopy(mBuff, aBuff, len);
|
||||
}
|
||||
|
||||
[[nodiscard]] tChar* getBuffer() {
|
||||
return mBuff;
|
||||
}
|
||||
|
||||
~StringData() {
|
||||
if (!mIsConst) delete[] mBuff;
|
||||
}
|
||||
|
||||
void resize(Index 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 StringData<tChar> Data;
|
||||
typedef typename Logic::Index Index;
|
||||
|
||||
enum {
|
||||
STRINGS_POOL_SIZE = 1024,
|
||||
MAX_INT_STRING_LENGTH = 10,
|
||||
MAX_BOOL_STRING_LENGTH = 10,
|
||||
MAX_FLOAT_STRING_LENGTH = 10,
|
||||
};
|
||||
static PoolAlloc<StringData<tChar>, STRINGS_POOL_SIZE> sStringPool;
|
||||
static Data sNullString;
|
||||
|
||||
private:
|
||||
Data* mData;
|
||||
|
||||
public: // Main Interface
|
||||
// Creates null string reference
|
||||
StringTemplate() {
|
||||
mData = &sNullString;
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
// References existing string data
|
||||
StringTemplate(const StringTemplate& in) {
|
||||
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.
|
||||
StringTemplate(const tChar* raw) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw, true);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
// Copies raw data and claims ownership over it
|
||||
StringTemplate(tChar* raw) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
~StringTemplate() {
|
||||
decReference(mData);
|
||||
}
|
||||
|
||||
private:
|
||||
static void incReference(Data* dp) {
|
||||
dp->mReferenceCount++;
|
||||
}
|
||||
|
||||
void decReference(Data* dp) {
|
||||
DEBUG_ASSERT(dp->mReferenceCount > 0)
|
||||
dp->mReferenceCount--;
|
||||
if (!dp->mReferenceCount) {
|
||||
mData->~StringData();
|
||||
sStringPool.deallocate(mData);
|
||||
}
|
||||
}
|
||||
|
||||
public: // Access
|
||||
// used to read data
|
||||
[[nodiscard]] const tChar* read() const {
|
||||
return mData->mBuff;
|
||||
}
|
||||
|
||||
// used to write data
|
||||
// output will be null if in TextEditing mode
|
||||
[[nodiscard]] tChar* write() {
|
||||
makeModifiable();
|
||||
return mData->getBuffer();
|
||||
}
|
||||
|
||||
// output will be null if in TextEditing mode
|
||||
tChar* resize(Index size) {
|
||||
makeModifiable();
|
||||
mData->resize(size);
|
||||
return write();
|
||||
}
|
||||
|
||||
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 (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 (mData->mIsConst) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(mData->mBuff);
|
||||
incReference(mData);
|
||||
}
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
auto size = this->size();
|
||||
ar << size;
|
||||
ar.writeBytes(read(), size);
|
||||
}
|
||||
|
||||
template<class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
Index size;
|
||||
ar >> size;
|
||||
resize(size);
|
||||
ar.readBytes(write(), size);
|
||||
}
|
||||
|
||||
public: // Syntax sugars
|
||||
|
||||
explicit StringTemplate(alni val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_INT_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit StringTemplate(alnf val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_FLOAT_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit StringTemplate(bool val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_BOOL_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit operator alni() {
|
||||
alni out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
explicit operator alnf() {
|
||||
alnf out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
explicit operator bool() {
|
||||
bool out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Index size() const {
|
||||
return Logic::calcLength(read());
|
||||
}
|
||||
|
||||
void calcLineOffsets(Buffer<Index>& aOut) const {
|
||||
Logic::calcLineOffsets(read(), size(), aOut);
|
||||
}
|
||||
|
||||
StringTemplate& operator=(tChar* in) {
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringTemplate& operator=(const tChar* in) {
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringTemplate& operator=(const StringTemplate& in) {
|
||||
if (&in == this) return *this;
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const StringTemplate& in) const {
|
||||
if (&in == this) return true;
|
||||
if (in.mData == mData) return true;
|
||||
return Logic::isEqualLogic(in.read(), read());
|
||||
}
|
||||
|
||||
StringTemplate operator+(const StringTemplate& in) const {
|
||||
StringTemplate out;
|
||||
auto const newSize = in.size() + size();
|
||||
out.resize(newSize);
|
||||
Logic::insertLogic(out.write(), newSize, read(), in.read(), size(), in.size());
|
||||
return out;
|
||||
}
|
||||
|
||||
public: // Debugging
|
||||
[[nodiscard]] ualni getReferenceCount() const { return mData->mReferenceCount; }
|
||||
[[nodiscard]] bool getIsConstFlag() const { return mData->mIsConst; }
|
||||
};
|
||||
|
||||
|
||||
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>;
|
||||
|
||||
template<typename tChar>
|
||||
ualni hash(StringTemplate<tChar> in) {
|
||||
return hash(in.read());
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "Allocators.hpp"
|
||||
#include "StringLogic.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
// Static data
|
||||
extern ModuleManifest gModuleStrings;
|
||||
|
||||
template <typename tChar>
|
||||
class StringTemplate;
|
||||
|
||||
// Hidden slave class
|
||||
template <typename tChar = int1>
|
||||
class StringData {
|
||||
friend StringTemplate<tChar>;
|
||||
typedef StringLogic<tChar> Logic;
|
||||
typedef typename StringLogic<tChar>::Index Index;
|
||||
|
||||
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 = 1;
|
||||
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(tChar* aBuff) {
|
||||
MODULE_SANITY_CHECK(gModuleStrings)
|
||||
DEBUG_ASSERT(aBuff)
|
||||
auto const len = Logic::calcLength(aBuff);
|
||||
mReferenceCount = 0;
|
||||
mIsConst = false;
|
||||
mEditedIdx = 0;
|
||||
mBuff = new tChar[len + 1];
|
||||
mBuff[len] = Logic::getEndChar();
|
||||
memCopy(mBuff, aBuff, len);
|
||||
}
|
||||
|
||||
[[nodiscard]] tChar* getBuffer() { return mBuff; }
|
||||
|
||||
~StringData() {
|
||||
if (!mIsConst) delete[] mBuff;
|
||||
}
|
||||
|
||||
void resize(Index 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 StringData<tChar> Data;
|
||||
typedef typename Logic::Index Index;
|
||||
|
||||
enum {
|
||||
STRINGS_POOL_SIZE = 1024,
|
||||
MAX_INT_STRING_LENGTH = 10,
|
||||
MAX_BOOL_STRING_LENGTH = 10,
|
||||
MAX_FLOAT_STRING_LENGTH = 10,
|
||||
};
|
||||
static PoolAlloc<StringData<tChar>, STRINGS_POOL_SIZE> sStringPool;
|
||||
static Data sNullString;
|
||||
|
||||
private:
|
||||
Data* mData;
|
||||
|
||||
public: // Main Interface
|
||||
// Creates null string reference
|
||||
StringTemplate() {
|
||||
mData = &sNullString;
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
// References existing string data
|
||||
StringTemplate(const StringTemplate& in) {
|
||||
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.
|
||||
StringTemplate(const tChar* raw) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw, true);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
// Copies raw data and claims ownership over it
|
||||
StringTemplate(tChar* raw) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
~StringTemplate() { decReference(mData); }
|
||||
|
||||
private:
|
||||
static void incReference(Data* dp) { dp->mReferenceCount++; }
|
||||
|
||||
void decReference(Data* dp) {
|
||||
DEBUG_ASSERT(dp->mReferenceCount > 0)
|
||||
dp->mReferenceCount--;
|
||||
if (!dp->mReferenceCount) {
|
||||
mData->~StringData();
|
||||
sStringPool.deallocate(mData);
|
||||
}
|
||||
}
|
||||
|
||||
public: // Access
|
||||
// used to read data
|
||||
[[nodiscard]] const tChar* read() const { return mData->mBuff; }
|
||||
|
||||
// used to write data
|
||||
// output will be null if in TextEditing mode
|
||||
[[nodiscard]] tChar* write() {
|
||||
makeModifiable();
|
||||
return mData->getBuffer();
|
||||
}
|
||||
|
||||
// output will be null if in TextEditing mode
|
||||
tChar* resize(Index size) {
|
||||
makeModifiable();
|
||||
mData->resize(size);
|
||||
return write();
|
||||
}
|
||||
|
||||
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 (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 (mData->mIsConst) {
|
||||
mData = new (sStringPool.allocate(0)) StringData(mData->mBuff);
|
||||
incReference(mData);
|
||||
}
|
||||
}
|
||||
|
||||
template <class tArchiver>
|
||||
void archiveWrite(tArchiver& ar) const {
|
||||
auto size = this->size();
|
||||
ar << size;
|
||||
ar.writeBytes(read(), size);
|
||||
}
|
||||
|
||||
template <class tArchiver>
|
||||
void archiveRead(tArchiver& ar) {
|
||||
Index size;
|
||||
ar >> size;
|
||||
resize(size);
|
||||
ar.readBytes(write(), size);
|
||||
}
|
||||
|
||||
public: // Syntax sugars
|
||||
explicit StringTemplate(alni val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_INT_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit StringTemplate(alnf val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_FLOAT_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit StringTemplate(bool val) {
|
||||
tChar raw[MAX_INT_STRING_LENGTH];
|
||||
Logic::convertValueToString(val, raw, MAX_BOOL_STRING_LENGTH);
|
||||
mData = new (sStringPool.allocate(0)) StringData(raw);
|
||||
incReference(mData);
|
||||
}
|
||||
|
||||
explicit operator alni() {
|
||||
alni out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
explicit operator alnf() {
|
||||
alnf out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
explicit operator bool() {
|
||||
bool out;
|
||||
Logic::convertStringToValue(read(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Index size() const { return Logic::calcLength(read()); }
|
||||
|
||||
void calcLineOffsets(Buffer<Index>& aOut) const { Logic::calcLineOffsets(read(), size(), aOut); }
|
||||
|
||||
StringTemplate& operator=(tChar* in) {
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringTemplate& operator=(const tChar* in) {
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringTemplate& operator=(const StringTemplate& in) {
|
||||
if (&in == this) return *this;
|
||||
this->~StringTemplate();
|
||||
new (this) StringTemplate(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const StringTemplate& in) const {
|
||||
if (&in == this) return true;
|
||||
if (in.mData == mData) return true;
|
||||
return Logic::isEqualLogic(in.read(), read());
|
||||
}
|
||||
|
||||
StringTemplate operator+(const StringTemplate& in) const {
|
||||
StringTemplate out;
|
||||
auto const newSize = in.size() + size();
|
||||
out.resize(newSize);
|
||||
Logic::insertLogic(out.write(), newSize, read(), in.read(), size(), in.size());
|
||||
return out;
|
||||
}
|
||||
|
||||
public: // Debugging
|
||||
[[nodiscard]] ualni getReferenceCount() const { return mData->mReferenceCount; }
|
||||
[[nodiscard]] bool getIsConstFlag() const { return mData->mIsConst; }
|
||||
};
|
||||
|
||||
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>;
|
||||
|
||||
template <typename tChar>
|
||||
ualni hash(StringTemplate<tChar> in) {
|
||||
return hash(in.read());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue