#include "daScript/misc/platform.h"
#include "daScript/simulate/runtime_string.h"
#include "daScript/simulate/simulate.h"
#include "daScript/simulate/hash.h"
#include "daScript/simulate/debug_print.h"
#include "daScript/simulate/runtime_string_delete.h"
#include "daScript/simulate/simulate_nodes.h"
#include "daScript/simulate/sim_policy.h"
namespace das
{
// string operations
vec4f SimPolicy_String::Add ( vec4f a, vec4f b, Context & context ) {
const char * sA = to_rts(a);
auto la = stringLength(context, sA);
const char * sB = to_rts(b);
auto lb = stringLength(context, sB);
uint32_t commonLength = la + lb;
if ( !commonLength ) {
return v_zero();
} else if ( char * sAB = (char * ) context.stringHeap->allocateString(nullptr, commonLength) ) {
memcpy ( sAB, sA, la );
memcpy ( sAB+la, sB, lb+1 );
return cast::from(sAB);
} else {
context.throw_error("can't add two strings, out of heap");
return v_zero();
}
}
void SimPolicy_String::SetAdd ( char * a, vec4f b, Context & context ) {
char ** pA = (char **)a;
const char * sA = *pA ? *pA : rts_null;
auto la = stringLength(context, sA);
const char * sB = to_rts(b);
auto lb = stringLength(context, sB);
uint32_t commonLength = la + lb;
if ( !commonLength ) {
// *pA = nullptr; is unnecessary, because its already nullptr
return;
} else if ( char * sAB = (char * ) context.stringHeap->allocateString(nullptr, commonLength) ) {
memcpy ( sAB, sA, la );
memcpy ( sAB+la, sB, lb+1 );
*pA = sAB;
context.stringHeap->recognize(sAB);
} else {
context.throw_error("can't add two strings, out of heap");
}
}
// helper functions
const char * rts_null = "";
string unescapeString ( const string & input, bool * error, bool ) {
if ( error ) *error = false;
const char* str = input.c_str();
const char* strEnd = str + input.length();
string result;
result.reserve(input.size());
for( ; str < strEnd; ++str ) {
if ( *str=='\\' ) {
++str;
if ( str == strEnd ) {
if ( error ) *error = true;
return result; // invalid escape sequence
}
switch ( *str ) {
case '"':
case '/':
case '\\': result += *str; break;
case 'b': result += '\b'; break;
case 'f': result += '\f'; break;
case 'n': result += '\n'; break;
case 'r': result += '\r'; break;
case 't': result += '\t'; break;
case 'u': DAS_ASSERTF(0, "utf-8 characters not supported yet"); break;
case '\n': break; // skip LF
case '{': result += '{'; break;
case '}': result += '}'; break;
case '\r': if ( str+1!=strEnd && str[1]=='\n' ) str++; break; // skip CR LF or just CR
default: result += *str; if ( error ) *error = true; break; // invalid escape character
}
} else
result += *str;
}
return result;
}
string escapeString ( const string & input, bool das_escape ) {
const char* str = input.c_str();
const char* strEnd = str + input.length();
string result;
result.reserve(input.size());
for( ; str < strEnd; ++str ) {
switch ( *str ) {
case '\"': result.append("\\\""); break;
case '\\': result.append("\\\\"); break;
case '\b': result.append("\\b"); break;
case '\f': result.append("\\f"); break;
case '\n': result.append("\\n"); break;
case '\r': result.append("\\r"); break;
case '\t': result.append("\\t"); break;
case '{': if (das_escape) result.append("\\{"); else result.append("{"); break;
case '}': if (das_escape) result.append("\\}"); else result.append("}"); break;
default: result.append(1, *str); break;
}
}
return result;
}
string getFewLines ( const char* st, int ROW, int COL, int LROW, int LCOL, int TAB ) {
TextWriter text;
int col=0, row=1;
auto it = st;
if ( ROW>1 ) {
while ( *it ) {
auto CH = *it++;
if ( CH=='\n' ) {
row++;
col=0;
if ( row==ROW ) break;
}
}
}
if ( row!=ROW ) return "";
while ( *it ) {
auto CH = *it++;
if ( CH=='\t' ) {
int tcol = (col + TAB) & ~(TAB-1);
while ( col < tcol ) {
text