// Copyright (c) 2009 DotNetAnywhere
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "Compat.h"
#include "Sys.h"
#include "System.String.h"
#include "MetaData.h"
#include "Types.h"
#include "Heap.h"
#include "Type.h"
#include "System.Array.h"
typedef struct tSystemString_ tSystemString;
// This structure must tie up with string.cs
struct tSystemString_ {
// Length in characters (not bytes)
U32 length;
// The characters
U16 chars[0];
};
// length in characters, not bytes
static tSystemString* CreateStringHeapObj(U32 len) {
tSystemString *pSystemString;
U32 totalSize;
totalSize = sizeof(tSystemString) + (len << 1);
pSystemString = (tSystemString*)Heap_Alloc(types[TYPE_SYSTEM_STRING], totalSize);
pSystemString->length = len;
return pSystemString;
}
tAsyncCall* System_String_ctor_CharInt32(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pSystemString;
CHAR2 c;
U32 i, len;
c = (CHAR2)(((U32*)pParams)[0]);
len = ((U32*)pParams)[1];
pSystemString = CreateStringHeapObj(len);
for (i=0; i<len; i++) {
pSystemString->chars[i] = c;
}
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)pSystemString;
return NULL;
}
tAsyncCall* System_String_ctor_CharAIntInt(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pSystemString;
HEAP_PTR charArray;
PTR charElements;
U32 startIndex, length;
charArray = ((HEAP_PTR*)pParams)[0];
startIndex = ((U32*)pParams)[1];
length = ((U32*)pParams)[2];
charElements = SystemArray_GetElements(charArray);
pSystemString = CreateStringHeapObj(length);
memcpy(pSystemString->chars, charElements + (startIndex << 1), length << 1);
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)pSystemString;
return NULL;
}
tAsyncCall* System_String_ctor_StringIntInt(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis, *pStr;
U32 startIndex, length;
pStr = ((tSystemString**)pParams)[0];
startIndex = ((U32*)pParams)[1];
length = ((U32*)pParams)[2];
pThis = CreateStringHeapObj(length);
memcpy(pThis->chars, &pStr->chars[startIndex], length << 1);
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)pThis;
return NULL;
}
tAsyncCall* System_String_get_Chars(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
U32 index;
index = *(U32*)pParams;
*(U32*)pReturnValue = pThis->chars[index];
return NULL;
}
tAsyncCall* System_String_InternalConcat(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *s0, *s1, *ret;
s0 = (tSystemString*)(((HEAP_PTR*)pParams)[0]);
s1 = (tSystemString*)(((HEAP_PTR*)pParams)[1]);
ret = CreateStringHeapObj(s0->length + s1->length);
memcpy(ret->chars, s0->chars, s0->length << 1);
memcpy(&ret->chars[s0->length], s1->chars, s1->length << 1);
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)ret;
return NULL;
}
tAsyncCall* System_String_InternalTrim(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
HEAP_PTR pWhiteChars;
U32 trimType, i, j, checkCharsLen;
U32 ofsStart, ofsEnd;
U16 *pCheckChars;
U32 isWhiteSpace;
tSystemString *pRet;
U16 c;
pWhiteChars = ((HEAP_PTR*)pParams)[0];
trimType = ((U32*)pParams)[1];
pCheckChars = (U16*)SystemArray_GetElements(pWhiteChars);
checkCharsLen = SystemArray_GetLength(pWhiteChars);
ofsStart = 0;
ofsEnd = pThis->length;
if (trimType & 1) {
// Trim start
for (i=ofsStart; i<ofsEnd; i++) {
// Check if each char is in the array
isWhiteSpace = 0;
c = pThis->chars[i];
for (j=0; j<checkCharsLen; j++) {
if (c == pCheckChars[j]) {
isWhiteSpace = 1;
break;
}
}
if (isWhiteSpace == 0) {
ofsStart = i;
break;
}
}
}
if (trimType & 2) {
// Trim end
for (i=ofsEnd-1; i>=ofsStart; i--) {
// Check if each char is in the array
isWhiteSpace = 0;
c = pThis->chars[i];
for (j=0; j<checkCharsLen; j++) {
if (c == pCheckChars[j]) {
isWhiteSpace = 1;
break;
}
}
if (isWhiteSpace == 0) {
ofsEnd = i + 1;
break;
}
}
}
pRet = CreateStringHeapObj(ofsEnd - ofsStart);
memcpy(pRet->chars, &pThis->chars[ofsStart], (ofsEnd - ofsStart) << 1);
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)pRet;
return NULL;
}
tAsyncCall* System_String_Equals(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *a, *b;
U32 ret;
a = ((tSystemString**)pParams)[0];
b = ((tSystemString**)pParams)[1];
if (a == b) {
ret = 1;
} else if (a == NULL || b == NULL || a->length != b->length) {
ret = 0;
} else {
ret = (memcmp(a->chars, b->chars, a->length<<1) == 0)?1:0;
}
*(U32*)pReturnValue = ret;
return NULL;
}
tAsyncCall* System_String_GetHashCode(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
U16 *pChar, *pEnd;
I32 hash;
hash = 0;
pChar = pThis->chars;
pEnd = pChar + pThis->length - 1;
for (; pChar < pEnd; pChar += 2) {
hash = (hash << 5) - hash + pChar[0];
hash = (hash << 5) - hash + pChar[1];
}
if (pChar <= pEnd) {
hash = (hash << 5) - hash + pChar[0];
}
*(I32*)pReturnValue = hash;
return NULL;
}
tAsyncCall* System_String_InternalReplace(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
tSystemString *pOld = ((tSystemString**)pParams)[0];
tSystemString *pNew = ((tSystemString**)pParams)[1];
tSystemString *pResult;
U32 thisLen, oldLen, newLen;
U16 *pThisChar0, *pOldChar0, *pNewChar0, *pResultChar0;
U32 i, j, replacements, dstIndex;
U32 resultLen;
// This function (correctly) assumes that the old string is not empty
thisLen = pThis->length;
oldLen = pOld->length;
newLen = pNew->length;
pThisChar0 = pThis->chars;
pOldChar0 = pOld->chars;
pNewChar0 = pNew->chars;
replacements = 0;
for (i=0; i<thisLen-oldLen+1; i++) {
U32 match = 1;
for (j=0; j<oldLen; j++) {
if (pThisChar0[i+j] != pOldChar0[j]) {
match = 0;
break;
}
}
if (match) {
i += oldLen - 1;
replacements++;
}
}
resultLen = thisLen - (oldLen - newLen) * replacements;
pResult = CreateStringHeapObj(resultLen);
pResultChar0 = pResult->chars;
dstIndex = 0;
for (i=0; i<thisLen; i++) {
U32 match;
if (i<thisLen-oldLen+1) {
for (j=0; j<oldLen; j++) {
match = 1;
if (pThisChar0[i+j] != pOldChar0[j]) {
match = 0;
break;
}
}
} else {
match = 0;
}
if (match) {
memcpy(&pResultChar0[dstIndex], pNewChar0, newLen << 1);
dstIndex += newLen;
i += oldLen - 1;
} else {
pResultChar0[dstIndex++] = pThisChar0[i];
}
}
*(HEAP_PTR*)pReturnValue = (HEAP_PTR)pResult;
return NULL;
}
tAsyncCall* System_String_InternalIndexOf(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
U16 value = ((U16*)pParams)[0];
I32 startIndex = ((I32*)pParams)[1];
I32 count = ((I32*)pParams)[2];
U32 forwards = ((U32*)pParams)[3];
I32 lastIndex;
I32 inc;
I32 i;
if (forwards) {
lastIndex = startIndex + count;
inc = 1;
i = startIndex;
} else {
lastIndex = startIndex - 1;
inc = -1;
i = startIndex + count - 1;
}
for (; i != lastIndex; i += inc) {
if (pThis->chars[i] == value) {
*(I32*)pReturnValue = i;
return NULL;
}
}
*(I32*)pReturnValue = -1;
return NULL;
}
tAsyncCall* System_String_InternalIndexOfAny(PTR pThis_, PTR pParams, PTR pReturnValue) {
tSystemString *pThis = (tSystemString*)pThis_;
HEAP_PTR valueArray = ((HEAP_PTR*)pParams)[0];
I32 startIndex = ((I32*)pParams)[1];
I32 count = ((I32*)pParams)[2];
U32 forwards = ((U32*)pParams)[3];
PTR valueChars = SystemArray_GetElements(valueArray);
U32 numValueChars = SystemArray_GetLength(valueArray);
I32 lastIndex;
I32 inc;
I32 i, j;
if (forwards) {
lastIndex = startIndex + count;
inc = 1;
i = startIndex;
} else {
lastIndex = startIndex - 1;
inc = -1;
i = startIndex + count - 1;
}
for (; i != lastIndex; i += inc) {
U16 thisChar = pThis->chars[i];
for (j=numValueChars - 1; j>=0; j--) {
if (thisChar == ((U16*)valueChars)[j]) {
*(I32*)pReturnValue = i;
return NULL;
}
}
}
*(I32*)pReturnValue = -1;
return NULL;
}
HEAP_PTR SystemString_FromUserStrings(tMetaData *pMetaData, IDX_USERSTRINGS index) {
unsigned int stringLen;
STRING2 string;
tSystemString *pSystemString;
string = MetaData_GetUserString(pMetaData, index, &stringLen);
// Note: stringLen is in bytes
pSystemString = (tSystemString*)CreateStringHeapObj(stringLen >> 1);
memcpy(pSystemString->chars, string, stringLen);
return (HEAP_PTR)pSystemString;
}
HEAP_PTR SystemString_FromCharPtrASCII(U8 *pStr) {
int stringLen, i;
tSystemString *pSystemString;
stringLen = (int)strlen(pStr);
pSystemString = CreateStringHeapObj(stringLen);
for (i=0; i<stringLen; i++) {
pSystemString->chars[i] = pStr[i];
}
return (HEAP_PTR)pSystemString;
}
HEAP_PTR SystemString_FromCharPtrUTF16(U16 *pStr) {
tSystemString *pSystemString;
int strLen = 0;
while (pStr[strLen] != 0) {
strLen++;
}
pSystemString = CreateStringHeapObj(strLen);
memcpy(pSystemString->chars, pStr, strLen << 1);
return (HEAP_PTR)pSystemString;
}
STRING2 SystemString_GetString(HEAP_PTR pThis_, U32 *pLength) {
tSystemString *pThis = (tSystemString*)pThis_;
if (pLength != NULL) {
*pLength = pThis->length;
}
return pThis->chars;
}
U32 SystemString_GetNumBytes(HEAP_PTR pThis_) {
return (((tSystemString*)pThis_)->length << 1) + sizeof(tSystemString);
}