I do have my own stringbuilder but i thought it was better do one in RLP to pick up speed. But it was not the case with my design.
But I think it is better to handle it in the managed side. So for me this thread is closed, if nothing better comes up. ???
Check it here .
Native code
struct Char
{
char charData; //ch stored in the Char
struct Char *next; //pointer to next Char
struct Char *prev; //pointer to previous Char
};
struct StringBuilder
{
struct Char *stNodeHead; //pointer to stNodeHead of list
struct Char *stNodeTail;//pointer to stNodeTail of list
unsigned int length;
unsigned int Id;
};
struct StringBuilderNode
{
struct StringBuilder *strBuild;
struct StringBuilderNode *next; //pointer to next Char
struct StringBuilderNode *prev; //pointer to previous Char
};
int ConstructStrBuildRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
return ConstructStringBuilder();
}
int DisposeStrBuildRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
unsigned int id = *(unsigned int*)args[0];
struct StringBuilderNode * strBuildNode = GetStringBuilderNode(id);
ClearStrBuild(strBuildNode->strBuild);
RemoveStrBuildNode(strBuildNode);
return 0;
}
int GetStringRLP(unsigned char *ch, void **args, unsigned int argsCount, unsigned int *argData)
{
int i, Length = *( int*)args[0];
unsigned int id = *(unsigned int*)args[1];
struct StringBuilder * strBuild = GetStringBuilder(id);
struct Char* curr = strBuild->stNodeHead;
for(i = 0; i < Length && (curr!=NULL); i++, curr=curr->next)
{
ch[i] = (unsigned char) curr->charData;
}
return strBuild->length;
}
int GetStringLengthRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
unsigned int id = *(unsigned int*)args[0];
struct StringBuilder * strBuild = GetStringBuilder(id);
return strBuild->length;
}
int AppendCharRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
unsigned int id = *(unsigned int*)args[1];
struct StringBuilder * strBuild = GetStringBuilder(id);
AddBack(*(char*)args[0],strBuild);
return strBuild->length;
}
int AppendStringRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
char * str = ( char*)args[0];
int i, Length = *( int*)args[1];
unsigned int id = *(unsigned int*)args[2];
struct StringBuilder * strBuild = GetStringBuilder(id);
for(i = 0; i < Length; i++)
{
AddBack(str[i],strBuild);
}
return strBuild->length;
}
int ContainsStringRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
char *find = ( char*)args[0];
int find_Length = *( int*)args[1];
unsigned int id = *(unsigned int*)args[2];
struct StringBuilder * strBuild = GetStringBuilder(id);
if(ContainsString(find,find_Length, strBuild) != NULL)
return 1;
return 0;
}
int ClearStrBuildRLP(void *none, void **args, unsigned int argsCount, unsigned int *argData)
{
unsigned int id = *(unsigned int*)args[0];
struct StringBuilder * strBuild = GetStringBuilder(id);
ClearStrBuild(strBuild);
strBuild->length = 0;
return 0;
}
struct Char* ContainsString(char * find, int length, struct StringBuilder * strBuild)
{
struct Char* subject;
struct Char* hold;
int i;
subject= strBuild->stNodeHead;
while(subject!=NULL)
{
if(subject->charData == find[0] )
{
//Hold here while testing
hold = subject;
for(i=0; i < length && subject != NULL; i++, subject=subject->next)
{
if (subject->charData != find [i] )
break;
else
if ( i + 1 >= length )
return hold;
}
//Continue search from last stop
subject = hold;
}
subject=subject->next;
}
return NULL;
}
void AddtBefore(char ch, struct Char *nodeB, struct StringBuilder * strBuild)
{
//insert a Char before nodeB
struct Char *newNode;
newNode= (struct Char *) RLPext->malloc(sizeof(struct Char));
newNode->prev=nodeB->prev;
newNode->next =nodeB;
newNode->charData =ch;
if(nodeB->prev==NULL)
{
strBuild->stNodeHead=newNode;
}
nodeB->prev=newNode;
RemoveChar(newNode,strBuild);
strBuild->length++;
}
void AddFront (char ch, struct StringBuilder * strBuild)
{
//insert a Char before the front Char
struct Char *newNode;
if(strBuild->stNodeHead==NULL)
{
newNode= (struct Char *) RLPext->malloc(sizeof(struct Char));
strBuild->stNodeHead=newNode;
strBuild->stNodeTail =newNode;
newNode->prev=NULL;
newNode->next=NULL;
newNode->charData=ch;
strBuild->length++;
}
else
{
AddtBefore(ch,strBuild->stNodeHead ,strBuild);
}
}
void AddAfter(char ch,struct Char *nodeB, struct StringBuilder * strBuild)
{
//insert a Char after nodeB
struct Char *newNode;
newNode= (struct Char *) RLPext->malloc(sizeof(struct Char));
newNode->next= nodeB->next ;
newNode->prev =nodeB;
newNode->charData =ch;
if(nodeB->next==NULL)
strBuild->stNodeTail =newNode;
nodeB->next=newNode;
strBuild->length++;
}
void AddBack (char ch, struct StringBuilder * strBuild)
{
//insert a Char after the last Char
if(strBuild->stNodeTail==NULL)
AddFront(ch,strBuild);
else
AddAfter(ch, strBuild->stNodeTail,strBuild );
}
int RemoveChar(struct Char *chNode, struct StringBuilder * strBuild)
{//remove a perticular Char
if((chNode==strBuild->stNodeTail) && (chNode==strBuild->stNodeHead) && (strBuild->stNodeHead != NULL))
{
RLPext->free(chNode);
chNode = NULL;
strBuild->stNodeHead = NULL;
strBuild->stNodeTail = NULL;
return 1;
}
else if( (chNode==strBuild->stNodeHead) && (strBuild->stNodeHead != NULL))
{
strBuild->stNodeHead=strBuild->stNodeHead->next;
strBuild->stNodeHead->prev=NULL;
RLPext->free(chNode);
return 1;
}
else if ( (chNode==strBuild->stNodeTail) && (strBuild->stNodeTail != NULL))
{
strBuild->stNodeTail=strBuild->stNodeTail->prev;
strBuild->stNodeTail->next=NULL ;
RLPext->free(chNode);
return 1;
}
else
{
chNode->prev->next=chNode->next;
chNode->next->prev=chNode->prev;
RLPext->free(chNode);
return 1;
}
return 0;
}
void ClearStrBuild(struct StringBuilder * strBuild)
{
while(strBuild->stNodeHead != NULL)
{
RemoveChar(strBuild->stNodeHead,strBuild);
}
strBuild->length = 0;
}
/***************************StringBuilder List******************************************/
struct StringBuilderNode *stNodeHead=NULL;
struct StringBuilderNode *stNodeTail = NULL;
static unsigned int stNodeIdCount = 10;
struct StringBuilderNode* GetStringBuilderNode(unsigned int id)
{
struct StringBuilderNode* currBuff;
for (currBuff = stNodeHead; currBuff != NULL; currBuff = currBuff->next)
{
if ( (currBuff->strBuild)->Id == id) return currBuff;
}
return NULL;
}
struct StringBuilder* GetStringBuilder(unsigned int id)
{
return GetStringBuilderNode(id)->strBuild;
}
struct StringBuilder* InitializeStringBuilder(unsigned int newId )
{
struct StringBuilder* newStrBuild = (struct StringBuilder *) RLPext->malloc(sizeof(struct StringBuilder));
if(newStrBuild==NULL)
{
return NULL; //Error
}
////Initializes the strBuild
newStrBuild->stNodeTail = NULL;
newStrBuild->stNodeHead = NULL;
newStrBuild->length = 0;
newStrBuild->Id = newId;
return newStrBuild; //Return new strBuild
}
unsigned int ConstructStringBuilder()
{
unsigned int id = stNodeIdCount;
struct StringBuilder* newStrBuild;
newStrBuild = InitializeStringBuilder(id);
stNodeIdCount++;
InsertStrTail(newStrBuild);
return id;
}
void ClearAllStrBuildNode()
{
while(stNodeHead != NULL)
{
RemoveStrBuildNode(stNodeHead);
}
}
int RemoveStringBuilder(unsigned int id)
{
struct StringBuilderNode* currBuff;
currBuff = GetStringBuilderNode(id);
return RemoveStrBuildNode(currBuff);
}
int RemoveStrBuildNode(struct StringBuilderNode *strBuildNode)
{
if((strBuildNode==stNodeTail) && (strBuildNode==stNodeHead) && (stNodeHead != NULL))
{
RLPext->free(strBuildNode);
strBuildNode = NULL;
stNodeHead = NULL;
stNodeTail = NULL;
return 1;
}
else if( (strBuildNode==stNodeHead) && (stNodeHead != NULL))
{
stNodeHead=stNodeHead->next;
stNodeHead->prev=NULL;
RLPext->free(strBuildNode);
return 1;
}
else if ( (strBuildNode==stNodeTail) && (stNodeTail != NULL))
{
stNodeTail=stNodeTail->prev;
stNodeTail->next=NULL ;
RLPext->free(strBuildNode);
return 1;
}
else
{
strBuildNode->prev->next=strBuildNode->next;
strBuildNode->next->prev=strBuildNode->prev;
RLPext->free(strBuildNode);
return 1;
}
return 0;
}
void InsertStrTail (struct StringBuilder *strBuild)
{
if(stNodeTail==NULL)
InsertStrHead(strBuild);
else
InsertStrAfter(strBuild, stNodeTail);
}
void InsertStrHead (struct StringBuilder* newBuff)
{
struct StringBuilderNode *newNode;
if(stNodeHead==NULL)
{
newNode= (struct StringBuilderNode *) RLPext->malloc(sizeof(struct StringBuilderNode));
stNodeHead=newNode;
stNodeTail =newNode;
newNode->prev=NULL;
newNode->next=NULL;
newNode->strBuild=newBuff;
}
else
{
InsertStrBefore(newBuff,stNodeHead );
}
}
void InsertStrAfter(struct StringBuilder* newBuff,struct StringBuilderNode *nodeB)
{
struct StringBuilderNode* newNode;
newNode = (struct StringBuilderNode *) RLPext->malloc(sizeof(struct StringBuilderNode));
newNode->next= nodeB->next ;
newNode->prev =nodeB;
newNode->strBuild =newBuff;
if(nodeB->next==NULL)
stNodeTail = newNode;
nodeB->next=newNode;
}
void InsertStrBefore(struct StringBuilder* newBuff, struct StringBuilderNode *nodeB)
{
struct StringBuilderNode *newNode;
newNode= (struct StringBuilderNode *) RLPext->malloc(sizeof(struct StringBuilderNode));
newNode->prev = nodeB->prev;
newNode->next = nodeB;
newNode->strBuild =newBuff;
if(nodeB->prev==NULL)
{
stNodeHead=newNode;
}
nodeB->prev=newNode;
RemoveStrBuildNode(newNode);//HACK: countStrBuild--;
}
And Managed code here
public class StringBuilderRLP
{
#region [Fields ]
static RLP.Procedure ConstructStrBuildRLP;
static RLP.Procedure DisposeStrBuildRLP;
static RLP.Procedure GetStringRLP;
static RLP.Procedure GetStringLengthRLP;
static RLP.Procedure AppendCharRLP;
static RLP.Procedure AppendStringRLP;
static RLP.Procedure ContainsStringRLP;
static RLP.Procedure ClearStrBuildRLP;
private int STRINGBUILDER_ID;
#endregion [Fields ]
#region [ Property ]
/// <summary>
/// Get the length of the string
/// </summary>
public int Length { get { if ( GetStringLengthRLP != null ) return GetStringLengthRLP.Invoke( STRINGBUILDER_ID ); else return 0; } }
#endregion [ Property ]
#region [ Constructors ]
#region [RLP]
public static void GetProcedure( byte [] elf_file )
{
try
{
if ( ConstructStrBuildRLP == null )
{
ConstructStrBuildRLP = RLP.GetProcedure( elf_file, "ConstructStrBuildRLP" );
DisposeStrBuildRLP = RLP.GetProcedure( elf_file, "DisposeStrBuildRLP" );
GetStringRLP = RLP.GetProcedure( elf_file, "GetStringRLP" );
GetStringLengthRLP = RLP.GetProcedure( elf_file, "GetStringLengthRLP" );
AppendCharRLP = RLP.GetProcedure( elf_file, "AppendCharRLP" );
AppendStringRLP = RLP.GetProcedure( elf_file, "AppendStringRLP" );
ContainsStringRLP = RLP.GetProcedure( elf_file, "ContainsStringRLP" );
ClearStrBuildRLP = RLP.GetProcedure( elf_file, "ClearStrBuildRLP" );
}
}
catch ( Exception )
{
throw;
}
}
#endregion [RLP]
public StringBuilderRLP( string InitialValue )
{
try
{
STRINGBUILDER_ID = ConstructStrBuildRLP.Invoke();
Append( InitialValue );
}
catch ( Exception )
{
throw;
}
}
public StringBuilderRLP()
{
try
{
STRINGBUILDER_ID = ConstructStrBuildRLP.Invoke();
}
catch ( Exception )
{
}
}
#endregion [ Constructors ]
#region [ Public Methods ]
public void Append( string stringToAppend )
{
if ( stringToAppend.Length == 0 ) return;
try
{
AppendStringRLP.Invoke( stringToAppend, stringToAppend.Length, STRINGBUILDER_ID );
}
catch ( Exception )
{
}
}
public void Append( char charToAppend )
{
try
{
AppendCharRLP.Invoke( charToAppend, STRINGBUILDER_ID );
}
catch ( Exception )
{
}
}
/// <summary>
/// Get the string
/// </summary>
/// <returns>The string that has been built</returns>
public override string ToString()
{
byte [] temp = null;
try
{
int size = Length;
if ( !(size > 0) ) return string.Empty;
temp = new byte [size];
if ( GetStringRLP != null )
GetStringRLP.InvokeEx( temp, size, STRINGBUILDER_ID );
return new string( temp.UTF8ByteArrayToChars() );
}
catch ( Exception )
{
}
finally
{
temp = null;
}
return string.Empty;
}
/// <summary>
/// Clear the string from memory
/// </summary>
public void Clear()
{
try
{
ClearStrBuildRLP.Invoke( STRINGBUILDER_ID );
}
catch ( Exception )
{
}
}
public bool Contains( string find )
{
try
{
if ( ContainsStringRLP.Invoke( find, find.Length, STRINGBUILDER_ID ) == 1 )
return true;
}
catch ( Exception )
{ }
return false;
}
#endregion [ Public Methods ]
#region [IDisposable Members]
public void Dispose()
{
try
{
if ( DisposeStrBuildRLP != null )
DisposeStrBuildRLP.Invoke( STRINGBUILDER_ID );
}
catch ( Exception )
{
}
}
#endregion [IDisposable Members]
}