string functions in the VM are now compatible with packed strings

added a StringToLocal UTF-8 version to the VM

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40184
This commit is contained in:
Borja Ferrer
2006-11-12 00:40:58 +00:00
parent e4ff973dbf
commit 4d89283924
3 changed files with 106 additions and 21 deletions
+90 -15
View File
@@ -481,22 +481,19 @@ int BaseContext::LocalToString(cell_t local_addr, char **addr)
return SP_ERROR_NONE;
}
int BaseContext::PushString(cell_t *local_addr, cell_t **phys_addr, const char *string)
int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
{
cell_t *ph_addr;
char *ph_addr;
int err;
unsigned int i, numcells = strlen(string);
unsigned int len, numcells = ((len=strlen(string)) + sizeof(cell_t)) / sizeof(cell_t);
if ((err = HeapAlloc(numcells+1, local_addr, &ph_addr)) != SP_ERROR_NONE)
if ((err = HeapAlloc(numcells, local_addr, (cell_t **)&ph_addr)) != SP_ERROR_NONE)
{
return err;
}
for (i=0; i<numcells; i++)
{
ph_addr[i] = (cell_t)string[i];
}
ph_addr[numcells] = '\0';
memcpy(ph_addr, string, len);
ph_addr[len] = '\0';
if ((err = PushCell(*local_addr)) != SP_ERROR_NONE)
{
@@ -514,8 +511,8 @@ int BaseContext::PushString(cell_t *local_addr, cell_t **phys_addr, const char *
int BaseContext::StringToLocal(cell_t local_addr, size_t chars, const char *source)
{
cell_t *dest;
int i, len;
char *dest;
int len;
if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
{
@@ -523,19 +520,97 @@ int BaseContext::StringToLocal(cell_t local_addr, size_t chars, const char *sour
}
len = strlen(source);
dest = (cell_t *)(ctx->memory + local_addr);
dest = (char *)(ctx->memory + local_addr);
if ((size_t)len >= chars)
{
len = chars - 1;
}
for (i=0; i<len; i++)
if (len <= 0)
{
dest[i] = (cell_t)source[i];
return SP_ERROR_NONE;
}
memcpy(dest, source, len);
dest[len] = '\0';
return SP_ERROR_NONE;
}
inline int __CheckValidChar(char *c)
{
int count;
int bytecount = 0;
for(count=1; (*c & 0xC0) == 0x80; count++)
{
c--;
}
switch (*c & 0xF0)
{
case 0xC0:
case 0xD0:
{
bytecount = 2;
break;
}
case 0xE0:
{
bytecount = 3;
break;
}
case 0xF0:
{
bytecount = 4;
break;
}
}
if (bytecount != count)
{
return count;
}
return 0;
}
int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
{
char *dest;
int len;
bool needtocheck = false;
if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
{
return SP_ERROR_INVALID_ADDRESS;
}
len = strlen(source);
dest = (char *)(ctx->memory + local_addr);
if ((size_t)len >= maxbytes)
{
len = maxbytes - 1;
needtocheck = true;
}
if (len <= 0)
{
return SP_ERROR_NONE;
}
memcpy(dest, source, len);
if ((dest[len] & 1<<7) && needtocheck)
{
len -= __CheckValidChar(dest+len-1);
}
dest[len] = '\0';
if (wrtnbytes)
{
*wrtnbytes = len;
}
return SP_ERROR_NONE;
}
+2 -1
View File
@@ -33,9 +33,10 @@ namespace SourcePawn
virtual int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
virtual int LocalToString(cell_t local_addr, char **addr);
virtual int StringToLocal(cell_t local_addr, size_t chars, const char *source);
virtual int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
virtual int PushCell(cell_t value);
virtual int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
virtual int PushString(cell_t *local_addr, cell_t **phys_addr, const char *string);
virtual int PushString(cell_t *local_addr, char **phys_addr, const char *string);
virtual int PushCellsFromArray(cell_t array[], unsigned int numcells);
virtual int BindNatives(sp_nativeinfo_t *natives, unsigned int num, int overwrite);
virtual int BindNative(sp_nativeinfo_t *native);