gates_of_skeldal/DDLReader/WStringProxy.cpp
2025-01-25 21:15:16 +01:00

185 lines
No EOL
5.8 KiB
C++
Raw Blame History

// WStringProxy.cpp: implementation of the WStringProxy class.
//
//////////////////////////////////////////////////////////////////////
#include "WStringProxy.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/** Funkce vytvo<76><6F> transitivn<76> uz<75>v<EFBFBD>r.
to znamen<65>, <20>e zru<72><75> v<>echny z<>et<65>zen<65> redirecty.
*/
WStringProxy *WStringProxy::TransitivniUzaver()
{
if (_operation==OpSubstr && _offset==0 && _stringSize==_baseString->GetLength())
{
WStringProxy *next=_baseString->TransitivniUzaver();
if (next==NULL) return this;
next->AddRef();
_baseString->Release();
_baseString=next;
return next;
}
return NULL;
}
/** Main render procedure
It creates allocates buffer proxy and renders tree into it
Then turns self into redirect proxy a redirect self into newly created string
Rerurns pointer to newly created proxy
*/
WStringProxy *WStringProxy::RenderString()
{
if (_operation==OpMemBlck) return this;
WStringProxy *pp=TransitivniUzaver();
if (pp!=NULL) return pp->_baseString->RenderString();
WStringProxy *newProxy=WStringMemory::AllocString(NULL,_stringSize);
wchar_t *renderPtr=const_cast<wchar_t *>(newProxy->GetStringFromMemBlock());
RenderStringToBuffer(renderPtr);
newProxy->AddRef();
this->~WStringProxy();
_operation=OpSubstr;
_offset=0;
_baseString=newProxy;
return newProxy;
}
/** Function renders simple effect into buffer
Function needs buffer with nul terminated string
*/
void WStringProxy::RenderSimpleEffect(wchar_t *renderPtr)
{
assert(_operation==OpEffect);
switch (_effect)
{
case EfLower: wcslwr(renderPtr);break;
case EfUpper: wcsupr(renderPtr);break;
case EfReverse: wcsrev(renderPtr);break;
}
}
/** Light phase of rendering. Used to render string that is not
created from substring. This part is optimized for concat and user effects
When substring must be rendered, function call RenderStringToBufferSubstr to
render substring.
*/
void WStringProxy::RenderStringToBuffer(wchar_t *renderPtr)
{
WStringMemory::LockProxy(this);
switch (_operation)
{
case OpConcat:
_baseString->RenderStringToBuffer(renderPtr);
_secondString->RenderStringToBuffer(renderPtr+_baseString->GetLength());
break;
case OpSubstr:
{
_baseString->RenderStringToBufferSubstr(renderPtr,_offset,GetLength());
}
break;
case OpMemBlck:
{
const wchar_t *str=GetStringFromMemBlock();
wcsncpy(renderPtr,str,_stringSize);
}
break;
case OpEffect:
{
uint32_t offset=0;
renderPtr[_stringSize]=0; //we can append zero, because right side of string is not yet rendered
//if this is end of string, one extra character for zero is also allocated.
//efect functions can rely on it.
if (_blockData2>=256) offset=_userEffect->PreRenderString(renderPtr,_baseString->GetLength()); //call prerender to prepare begin of buffer
_baseString->RenderStringToBuffer(renderPtr+offset); //render string to rest of buffer
if (_blockData2>=256) _userEffect->RenderString(renderPtr,_baseString->GetLength()); //apply effect to buffer
else RenderSimpleEffect(renderPtr);
}
break;
};
WStringMemory::UnlockProxy(this);
}
/**
Deep phase of rendering. Function can render substrings, or render substring of two
concated strings. Function can also perform partial effect on string. Function cannot
handle partial user effect, so this effects are converted to things strings.
*/
void WStringProxy::RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size)
{
WStringMemory::LockProxy(this);
switch (_operation)
{
case OpConcat:
{
//process substring of concat
//count characters in buffer
size_t rendered;
//when string starts in left string
if (_baseString->GetLength()>offset)
{
//calculate total characters that may be rendered
rendered=_baseString->GetLength()-offset;
//but limit it to request size
if (rendered>size) rendered=size;
//render substring into buffer
_baseString->RenderStringToBufferSubstr(renderPtr,offset,rendered);
}
else
//no character has been rendered
rendered=0;
//there is still characters remained to render. We will take it from second string
if (size-rendered>0)
{
if (offset>_baseString->GetLength()) offset-=_baseString->GetLength();
else offset=0;
_secondString->RenderStringToBufferSubstr(renderPtr+rendered,offset,size-rendered);
}
}
break;
case OpSubstr:
{ //rendering substrings is very easy
offset+=_offset; //add offset of substring
assert(offset+size<=GetLength()); //check length
//render substring
this->RenderStringToBufferSubstr(renderPtr,offset,size);
}
break;
case OpMemBlck:
{
//rendering from memory, final stop in recursion
//Get pointer string
const wchar_t *str=GetStringFromMemBlock();
//copy substring from string into render buffer
wcsncpy(renderPtr,str+offset,size);
}
break;
case OpEffect:
if (_blockData2>=256) //interface cannot handle partial rendering
{
RenderString(); //convert proxy to simple redirect and render it
RenderStringToBufferSubstr(renderPtr,offset,size); //now we are able to cut out part
}
else
{
//all standard effects maps string 1:1
//first get content of substring into buffer
_baseString->RenderStringToBufferSubstr(renderPtr,offset,size);
//we can append zero, because right side of string is not yet rendered
renderPtr[size]=0;
//process effect on target
RenderSimpleEffect(renderPtr);
}
break;
};
WStringMemory::UnlockProxy(this);
}