impl strings.cc

This commit is contained in:
fusion32 2025-05-29 00:04:19 -03:00
parent 565d28e480
commit e5b60ae075
5 changed files with 212 additions and 374 deletions

View File

@ -2667,339 +2667,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
// WARNING: Variable defined which should be unmapped: p
char * AddStaticString(char *String)
{
size_t sVar1;
char *__dest;
listnode<> *plVar2;
TStaticStringTableBlock *pTVar3;
listIterator<> iter;
TStaticStringTableBlock *local_18;
char *p;
sVar1 = strlen(String);
if ((int)sVar1 < 0x10000) {
__dest = "";
if (sVar1 != 0) {
for (plVar2 = StaticStringTable.firstNode; plVar2 != (listnode<> *)0x0;
plVar2 = plVar2->next) {
if ((int)(sVar1 + 1) < 0x10000 - (plVar2->data).TotalTextLength) {
if (plVar2 != (listnode<> *)0x0) goto LAB_0805197a;
break;
}
}
plVar2 = list<>::append(&StaticStringTable);
if (plVar2 == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
pTVar3 = (TStaticStringTableBlock *)0x0;
}
else {
pTVar3 = &plVar2->data;
}
pTVar3->TotalTextLength = 0;
if (plVar2 == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
local_18 = (TStaticStringTableBlock *)0x0;
}
else {
LAB_0805197a:
local_18 = &plVar2->data;
}
if (plVar2 == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
pTVar3 = (TStaticStringTableBlock *)0x0;
}
else {
pTVar3 = &plVar2->data;
}
__dest = local_18->Text + pTVar3->TotalTextLength;
memcpy(__dest,String,sVar1 + 1);
if (plVar2 == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
pTVar3 = (TStaticStringTableBlock *)0x0;
}
else {
pTVar3 = &plVar2->data;
}
pTVar3->TotalTextLength = sVar1 + pTVar3->TotalTextLength + 1;
}
}
else {
error("AddStaticString: String zu lang (%d).\n",sVar1);
__dest = (char *)0x0;
}
return __dest;
}
// WARNING: Variable defined which should be unmapped: iter
ulong AddDynamicString(char *String)
{
int iVar1;
int i_1;
size_t sVar2;
int i;
int iVar3;
TDynamicStringTableBlock *pTVar4;
int pos;
int iVar5;
int local_18;
int count;
listIterator<> iter;
sVar2 = strlen(String);
if ((int)sVar2 < 0x8000) {
if (sVar2 == 0) {
return 0;
}
local_18 = 0;
count = (int)DynamicStringTable.firstNode;
while ((listnode<> *)count != (listnode<> *)0x0) {
if (0 < (((listnode<> *)count)->data).FreeEntries) {
if ((listnode<> *)count == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
pTVar4 = (TDynamicStringTableBlock *)0x0;
}
else {
pTVar4 = &((listnode<> *)count)->data;
}
if ((int)(sVar2 + 1) < 0x8000 - pTVar4->TotalTextLength) {
if ((listnode<> *)count != (listnode<> *)0x0) goto LAB_08051ae9;
break;
}
}
if ((listnode<> *)count == (listnode<> *)0x0) {
error("listIterator::operator++: Iterator ist NULL.\n");
}
else {
count = (int)((listnode<> *)count)->next;
}
local_18 = local_18 + 1;
}
count = (int)list<>::append(&DynamicStringTable);
if ((listnode<> *)count == (listnode<> *)0x0) {
error("listIterator::operator*: Iterator ist NULL.\n");
pTVar4 = (TDynamicStringTableBlock *)0x0;
}
else {
pTVar4 = &((listnode<> *)count)->data;
}
pTVar4->FreeEntries = 0x100;
iVar3 = 0;
pTVar4->TotalTextLength = 0;
pTVar4->Dirty = false;
do {
pTVar4->EntryType[iVar3] = '\0';
iVar3 = iVar3 + 1;
} while (iVar3 < 0x100);
if ((listnode<> *)count == (listnode<> *)0x0) {
pTVar4 = (TDynamicStringTableBlock *)0x0;
error("listIterator::operator*: Iterator ist NULL.\n");
}
else {
LAB_08051ae9:
pTVar4 = &((listnode<> *)count)->data;
}
iVar3 = 0;
do {
iVar5 = iVar3;
if (pTVar4->EntryType[iVar3] == '\0') break;
iVar3 = iVar3 + 1;
iVar5 = -1;
} while (iVar3 < 0x100);
if (iVar5 != -1) {
iVar1 = pTVar4->TotalTextLength;
pTVar4->EntryType[iVar5] = '\x01';
iVar3 = pTVar4->TotalTextLength;
pTVar4->FreeEntries = pTVar4->FreeEntries + -1;
pTVar4->StringOffset[iVar5] = (ushort)iVar1;
memcpy(pTVar4->Text + iVar3,String,sVar2 + 1);
pTVar4->TotalTextLength = sVar2 + pTVar4->TotalTextLength + 1;
return iVar5 + 1 + local_18 * 0x100;
}
error("AddDynamicString: Keinen freien Platz gefunden.\n");
}
else {
error("AddDynamicString: String zu lang (%d)\n",sVar2);
}
return 0;
}
// WARNING: Variable defined which should be unmapped: iter
char * GetDynamicString(ulong Number)
{
int count;
int iVar1;
int Block;
uint uVar2;
uint uVar3;
char *Text;
listnode<> *local_10;
listIterator<> iter;
if (Number == 0) {
return (char *)0x0;
}
uVar2 = Number - 1 >> 8;
iVar1 = 0;
uVar3 = Number - 1 & 0xff;
local_10 = DynamicStringTable.firstNode;
if (uVar2 == 0) {
LAB_08051c50:
if (local_10 != (listnode<> *)0x0) {
if ((local_10->data).EntryType[uVar3] == '\x01') {
return (local_10->data).Text + (local_10->data).StringOffset[uVar3];
}
Text = &DAT_080f0540;
goto LAB_08051c3a;
}
}
else if (DynamicStringTable.firstNode != (listnode<> *)0x0) {
do {
local_10 = local_10->next;
iVar1 = iVar1 + 1;
if ((int)uVar2 <= iVar1) goto LAB_08051c50;
} while (local_10 != (listnode<> *)0x0);
}
Text = &DAT_080f0500;
LAB_08051c3a:
error(Text,Number);
return (char *)0x0;
}
// WARNING: Variable defined which should be unmapped: iter
void DeleteDynamicString(ulong Number)
{
int count;
int iVar1;
int Block;
uint uVar2;
uint uVar3;
char *Text;
listnode<> *local_10;
listIterator<> iter;
if (Number == 0) {
return;
}
uVar2 = Number - 1 >> 8;
iVar1 = 0;
uVar3 = Number - 1 & 0xff;
local_10 = DynamicStringTable.firstNode;
if (uVar2 == 0) {
LAB_08051ce0:
if (local_10 != (listnode<> *)0x0) {
if ((local_10->data).EntryType[uVar3] == '\x01') {
(local_10->data).EntryType[uVar3] = '\x02';
(local_10->data).Dirty = true;
return;
}
Text = &DAT_080f05c0;
goto LAB_08051cca;
}
}
else if (DynamicStringTable.firstNode != (listnode<> *)0x0) {
do {
local_10 = local_10->next;
iVar1 = iVar1 + 1;
if ((int)uVar2 <= iVar1) goto LAB_08051ce0;
} while (local_10 != (listnode<> *)0x0);
}
Text = &DAT_080f0580;
LAB_08051cca:
error(Text,Number);
return;
}
// WARNING: Variable defined which should be unmapped: iter
// WARNING: Unknown calling convention -- yet parameter storage is locked
void CleanupDynamicStrings(void)
{
int *piVar1;
int iVar2;
char *__s;
ushort uVar3;
int Help;
size_t sVar4;
int j;
int iVar5;
int Offset;
uint uVar6;
int Length;
int local_18;
int i;
listIterator<> iter;
i = (int)DynamicStringTable.firstNode;
if (DynamicStringTable.firstNode != (listnode<> *)0x0) {
do {
piVar1 = (int *)(i + 8);
if (*(char *)(i + 0x10) != '\0') {
local_18 = 0;
do {
if (*(char *)(local_18 + 9 + (int)piVar1) == '\x02') {
uVar6 = (uint)*(ushort *)(i + 0x112 + local_18 * 2);
__s = (char *)(uVar6 + 0x30a + (int)piVar1);
sVar4 = strlen(__s);
iVar2 = sVar4 + 1;
*(int *)(i + 0xc) = *(int *)(i + 0xc) - iVar2;
*(undefined1 *)(local_18 + 9 + (int)piVar1) = 0;
if ((int)(iVar2 + uVar6) < 0x8001) {
sVar4 = (-iVar2 - uVar6) + 0x8000;
if (0 < (int)sVar4) {
memmove(__s,(void *)(iVar2 + uVar6 + 0x30a + (int)piVar1),sVar4);
}
*piVar1 = *piVar1 + 1;
iVar5 = 0;
do {
if ((*(char *)(iVar5 + 9 + (int)piVar1) != '\0') &&
(uVar3 = *(ushort *)(i + 0x112 + iVar5 * 2), uVar6 < uVar3)) {
*(ushort *)(i + 0x112 + iVar5 * 2) = uVar3 - (short)iVar2;
}
iVar5 = iVar5 + 1;
} while (iVar5 < 0x100);
}
else {
error("CleanupDynamicStrings: Stringende fehlt\n");
}
}
local_18 = local_18 + 1;
} while (local_18 < 0x100);
*(undefined1 *)(i + 0x10) = 0;
}
if (i == 0) {
error("listIterator::operator++: Iterator ist NULL.\n");
}
else {
i = *(int *)i;
}
} while (i != 0);
}
return;
}
bool IsCountable(char *s)
{
@ -3809,28 +3476,6 @@ char * Capitals(char *Text)
return Text;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
void InitStrings(void)
{
return;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
void ExitStrings(void)
{
return;
}
void __tcf_0(void *param_1)
{

View File

@ -197,15 +197,6 @@ struct TAttackWave {
struct vector<TItemData> ExtraItem;
};
struct TDynamicStringTableBlock {
int FreeEntries;
int TotalTextLength;
bool Dirty;
uchar EntryType[256];
ushort StringOffset[256];
char Text[32768];
};
struct TNonplayer {
struct TCreature super_TCreature; // INHERITANCE?
enum STATE State;
@ -254,11 +245,6 @@ struct TMonsterhome {
int Timer;
};
struct TStaticStringTableBlock {
int TotalTextLength;
char Text[65536];
};
struct TCondition {
int Type;
ulong Text;

View File

@ -117,6 +117,11 @@ void ExitSHMExtern(void);
// strings.cc
// =============================================================================
const char *AddStaticString(const char *String);
uint32 AddDynamicString(const char *String);
const char *GetDynamicString(uint32 Number);
void DeleteDynamicString(uint32 Number);
void CleanupDynamicStrings(void);
void InitStrings(void);
void ExitStrings(void);

View File

@ -1,4 +1,211 @@
#include "common.hh"
#include "containers.hh"
struct TStaticStringTableBlock {
int TotalTextLength;
char Text[65536];
};
struct TDynamicStringTableBlock {
int FreeEntries;
int TotalTextLength;
bool Dirty;
uint8 EntryType[256];
uint16 StringOffset[256];
char Text[32768];
};
constexpr int StaticBlockSize = NARRAY(TStaticStringTableBlock::Text);
constexpr int DynamicBlockSize = NARRAY(TDynamicStringTableBlock::Text);
constexpr int DynamicBlockEntries = NARRAY(TDynamicStringTableBlock::EntryType);
enum : uint8 {
DYNAMIC_STRING_FREE = 0,
DYNAMIC_STRING_ALLOCATED = 1,
DYNAMIC_STRING_DELETED = 2,
};
static list<TStaticStringTableBlock> StaticStringTable;
static list<TDynamicStringTableBlock> DynamicStringTable;
const char *AddStaticString(const char *String){
int StringLen = (int)strlen(String);
if((StringLen + 1) > StaticBlockSize){
error("AddStaticString: String zu lang (%d).\n", StringLen);
return NULL;
}
if(StringLen == 0){
return "";
}
listnode<TStaticStringTableBlock> *Node = StaticStringTable.firstNode;
while(Node != NULL){
if((Node->data.TotalTextLength + StringLen + 1) <= StaticBlockSize){
break;
}
Node = Node->next;
}
if(Node == NULL){
Node = StaticStringTable.append();
memset(&Node->data, 0, sizeof(TStaticStringTableBlock));
}
TStaticStringTableBlock *Block = &Node->data;
char *Result = &Block->Text[Block->TotalTextLength];
memcpy(Result, String, StringLen + 1);
Block->TotalTextLength += StringLen + 1;
return Result;
}
uint32 AddDynamicString(const char *String){
int StringLen = (int)strlen(String);
if((StringLen + 1) > DynamicBlockSize){
error("AddDynamicString: String zu lang (%d)\n", StringLen);
return 0;
}
if(StringLen == 0){
return 0;
}
int BlockIndex = 0;
listnode<TDynamicStringTableBlock> *Node = DynamicStringTable.firstNode;
while(Node != NULL){
if(Node->data.FreeEntries > 0){
if((Node->data.TotalTextLength + StringLen + 1) <= DynamicBlockSize){
break;
}
}
Node = Node->next;
BlockIndex += 1;
}
if(Node == NULL){
Node = DynamicStringTable.append();
memset(&Node->data, 0, sizeof(TDynamicStringTableBlock));
Node->data.FreeEntries = DynamicBlockEntries;
}
TDynamicStringTableBlock *Block = &Node->data;
int EntryIndex = -1;
for(int i = 0; i < DynamicBlockEntries; i += 1){
if(Block->EntryType[i] == DYNAMIC_STRING_FREE){
EntryIndex = i;
break;
}
}
if(EntryIndex == -1){
error("AddDynamicString: Keinen freien Platz gefunden.\n");
return 0;
}
int StringOffset = Block->TotalTextLength;
Block->FreeEntries -= 1;
Block->TotalTextLength += StringLen + 1;
Block->EntryType[EntryIndex] = DYNAMIC_STRING_ALLOCATED;
Block->StringOffset[EntryIndex] = (uint16)StringOffset;
memcpy(&Block->Text[StringOffset], String, StringLen + 1);
return (uint32)(1 + BlockIndex * DynamicBlockEntries + EntryIndex);
}
const char *GetDynamicString(uint32 Number){
if(Number == 0){
return NULL;
}
int BlockIndex = (int)(Number - 1) / DynamicBlockEntries;
int EntryIndex = (int)(Number - 1) % DynamicBlockEntries;
listnode<TDynamicStringTableBlock> *Node = DynamicStringTable.firstNode;
while(BlockIndex > 0 && Node != NULL){
Node = Node->next;
BlockIndex -= 1;
}
if(Node == NULL){
error("GetDynamicString: Block für String %u existiert nicht\n", Number);
return NULL;
}
TDynamicStringTableBlock *Block = &Node->data;
if(Block->EntryType[EntryIndex] != DYNAMIC_STRING_ALLOCATED){
error("GetDynamicString: Eintrag für String %u existiert nicht\n", Number);
return NULL;
}
int StringOffset = (int)Block->StringOffset[EntryIndex];
return &Block->Text[StringOffset];
}
void DeleteDynamicString(uint32 Number){
if(Number == 0){
return;
}
int BlockIndex = (int)(Number - 1) / DynamicBlockEntries;
int EntryIndex = (int)(Number - 1) % DynamicBlockEntries;
listnode<TDynamicStringTableBlock> *Node = DynamicStringTable.firstNode;
while(BlockIndex > 0 && Node != NULL){
Node = Node->next;
BlockIndex -= 1;
}
if(Node == NULL){
error("DeleteDynamicString: Block für String %u existiert nicht\n", Number);
return;
}
TDynamicStringTableBlock *Block = &Node->data;
if(Block->EntryType[EntryIndex] != DYNAMIC_STRING_ALLOCATED){
error("DeleteDynamicString: Eintrag für String %u existiert nicht\n", Number);
return;
}
Block->EntryType[EntryIndex] = DYNAMIC_STRING_DELETED;
Block->Dirty = true;
}
void CleanupDynamicStrings(void){
// IMPORTANT(fusion): The way we manage dynamic strings also mean pointers
// returned from `GetDynamicString` aren't stable.
for(listnode<TDynamicStringTableBlock> *Node = DynamicStringTable.firstNode;
Node != NULL;
Node = Node->next){
TDynamicStringTableBlock *Block = &Node->data;
if(!Block->Dirty){
continue;
}
for(int i = 0; i < DynamicBlockEntries; i += 1){
if(Block->EntryType[i] == DYNAMIC_STRING_DELETED){
int StringOffset = Block->StringOffset[i];
char *String = &Block->Text[StringOffset];
int StringLen = (int)strlen(String);
int StringEnd = StringOffset + StringLen + 1;
Block->EntryType[i] = DYNAMIC_STRING_FREE;
if(StringEnd > DynamicBlockSize){
error("CleanupDynamicStrings: Stringende fehlt\n");
continue;
}
if(StringEnd < DynamicBlockSize){
memmove(String, String + StringEnd, DynamicBlockSize - StringEnd);
}
for(int j = 0; j < DynamicBlockEntries; j += 1){
if(Block->EntryType[j] != DYNAMIC_STRING_FREE
&& Block->StringOffset[j] > StringOffset){
Block->StringOffset[j] -= StringLen + 1;
}
}
}
}
}
}
void InitStrings(void){
// no-op

View File

@ -15,18 +15,13 @@ typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, const
typedef void TSendMailsFunction(TPlayerData *PlayerData);
extern void AbortWriter(void);
extern uint32 AddDynamicString(const char *String);
extern const char *AddStaticString(const char *String);
extern void AnnounceChangedCreature(uint32 CreatureID, int Type);
extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void Change(Object Obj, ObjectType NewType, uint32 Value);
extern bool CheckRight(uint32 CreatureID, RIGHT Right);
extern void CleanHouseField(int x, int y, int z);
extern void CleanupDynamicStrings(void);
extern void CreatePlayerList(bool Online);
extern void DeleteDynamicString(uint32 Number);
extern TCreature *GetCreature(uint32 CreatureID);
extern const char *GetDynamicString(uint32 Number);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);