Blob Blame History Raw
From 5c1a0eda98fbea03e7c6ea29e7d18f9329e7c29d Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Date: Mon, 20 Nov 2017 14:02:33 +0100
Subject: [PATCH 4/4] libs: update angelscript to 2.32.0

Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
---
 src/scriptengine/script_engine.cpp         |   2 +-
 src/scriptengine/scriptarray.cpp           | 480 ++++++++++++------
 src/scriptengine/scriptarray.hpp           |  40 +-
 src/scriptengine/scriptstdstring.cpp       | 758 +++++++++++++++++------------
 src/scriptengine/scriptstdstring.hpp       |  16 +-
 src/scriptengine/scriptstdstring_utils.cpp |   2 +-
 6 files changed, 789 insertions(+), 509 deletions(-)

diff --git a/src/scriptengine/script_engine.cpp b/src/scriptengine/script_engine.cpp
index 47458c93d..2c1ccbf3e 100644
--- a/src/scriptengine/script_engine.cpp
+++ b/src/scriptengine/script_engine.cpp
@@ -222,7 +222,7 @@ namespace Scripting
     /*
     void ScriptEngine::runMethod(asIScriptObject* obj, std::string methodName)
     {
-        asIObjectType* type = obj->GetObjectType();
+        asITypeInfo* type = obj->GetObjectType();
         asIScriptFunction* method = type->GetMethodByName(methodName.c_str());
         if (method == NULL)
             Log::error("Scripting", ("runMethod: object does not implement method " + methodName).c_str());
diff --git a/src/scriptengine/scriptarray.cpp b/src/scriptengine/scriptarray.cpp
index 322cdfa17..8557c8cb9 100644
--- a/src/scriptengine/scriptarray.cpp
+++ b/src/scriptengine/scriptarray.cpp
@@ -1,38 +1,9 @@
-/*
-AngelCode Scripting Library
-Copyright (c) 2003-2015 Andreas Jonsson
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you
-must not claim that you wrote the original software. If you use
-this software in a product, an acknowledgment in the product
-documentation would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-
-The original version of this library can be located at:
-http://www.angelcode.com/angelscript/
-
-Andreas Jonsson
-andreas@angelcode.com
-*/
-
 #include <new>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <stdio.h> // sprintf
+#include <string>
 
 #include "scriptarray.hpp"
 
@@ -79,7 +50,7 @@ struct SArrayCache
 // through 1999 for this purpose, so we should be fine.
 const asPWORD ARRAY_CACHE = 1000;
 
-static void CleanupObjectTypeArrayCache(asIObjectType *type)
+static void CleanupTypeInfoArrayCache(asITypeInfo *type)
 {
 	SArrayCache *cache = reinterpret_cast<SArrayCache*>(type->GetUserData(ARRAY_CACHE));
 	if( cache )
@@ -89,14 +60,13 @@ static void CleanupObjectTypeArrayCache(asIObjectType *type)
 	}
 }
 
-CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length)
+CScriptArray* CScriptArray::Create(asITypeInfo *ti, asUINT length)
 {
-	asIScriptContext *ctx = asGetActiveContext();
-
 	// Allocate the memory
 	void *mem = userAlloc(sizeof(CScriptArray));
 	if( mem == 0 )
 	{
+		asIScriptContext *ctx = asGetActiveContext();
 		if( ctx )
 			ctx->SetException("Out of memory");
 
@@ -104,27 +74,18 @@ CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length)
 	}
 
 	// Initialize the object
-	CScriptArray *a = new(mem) CScriptArray(length, ot);
-
-	// It's possible the constructor raised a script exception, in which case we
-	// need to free the memory and return null instead, else we get a memory leak.
-	if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
-	{
-		a->Release();
-		return 0;
-	}
+	CScriptArray *a = new(mem) CScriptArray(length, ti);
 
 	return a;
 }
 
-CScriptArray* CScriptArray::Create(asIObjectType *ot, void *initList)
+CScriptArray* CScriptArray::Create(asITypeInfo *ti, void *initList)
 {
-	asIScriptContext *ctx = asGetActiveContext();
-
 	// Allocate the memory
 	void *mem = userAlloc(sizeof(CScriptArray));
 	if( mem == 0 )
 	{
+		asIScriptContext *ctx = asGetActiveContext();
 		if( ctx )
 			ctx->SetException("Out of memory");
 
@@ -132,27 +93,18 @@ CScriptArray* CScriptArray::Create(asIObjectType *ot, void *initList)
 	}
 
 	// Initialize the object
-	CScriptArray *a = new(mem) CScriptArray(ot, initList);
-
-	// It's possible the constructor raised a script exception, in which case we
-	// need to free the memory and return null instead, else we get a memory leak.
-	if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
-	{
-		a->Release();
-		return 0;
-	}
+	CScriptArray *a = new(mem) CScriptArray(ti, initList);
 
 	return a;
 }
 
-CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length, void *defVal)
+CScriptArray* CScriptArray::Create(asITypeInfo *ti, asUINT length, void *defVal)
 {
-	asIScriptContext *ctx = asGetActiveContext();
-
 	// Allocate the memory
 	void *mem = userAlloc(sizeof(CScriptArray));
 	if( mem == 0 )
 	{
+		asIScriptContext *ctx = asGetActiveContext();
 		if( ctx )
 			ctx->SetException("Out of memory");
 
@@ -160,22 +112,14 @@ CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length, void *defVa
 	}
 
 	// Initialize the object
-	CScriptArray *a = new(mem) CScriptArray(length, defVal, ot);
-
-	// It's possible the constructor raised a script exception, in which case we
-	// need to free the memory and return null instead, else we get a memory leak.
-	if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
-	{
-		a->Release();
-		return 0;
-	}
+	CScriptArray *a = new(mem) CScriptArray(length, defVal, ti);
 
 	return a;
 }
 
-CScriptArray* CScriptArray::Create(asIObjectType *ot)
+CScriptArray* CScriptArray::Create(asITypeInfo *ti)
 {
-	return CScriptArray::Create(ot, asUINT(0));
+	return CScriptArray::Create(ti, asUINT(0));
 }
 
 // This optional callback is called when the template type is first used by the compiler.
@@ -183,16 +127,16 @@ CScriptArray* CScriptArray::Create(asIObjectType *ot)
 // subtype at compile time, instead of at runtime. The output argument dontGarbageCollect
 // allow the callback to tell the engine if the template instance type shouldn't be garbage collected,
 // i.e. no asOBJ_GC flag.
-static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageCollect)
+static bool ScriptArrayTemplateCallback(asITypeInfo *ti, bool &dontGarbageCollect)
 {
 	// Make sure the subtype can be instantiated with a default factory/constructor,
 	// otherwise we won't be able to instantiate the elements.
-	int typeId = ot->GetSubTypeId();
+	int typeId = ti->GetSubTypeId();
 	if( typeId == asTYPEID_VOID )
 		return false;
 	if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) )
 	{
-		asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId);
+		asITypeInfo *subtype = ti->GetEngine()->GetTypeInfoById(typeId);
 		asDWORD flags = subtype->GetFlags();
 		if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) )
 		{
@@ -215,7 +159,8 @@ static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageColl
 			if( !found )
 			{
 				// There is no default constructor
-				ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default constructor");
+				// TODO: Should format the message to give the name of the subtype for better understanding
+				ti->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default constructor");
 				return false;
 			}
 		}
@@ -225,7 +170,7 @@ static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageColl
 
 			// If value assignment for ref type has been disabled then the array
 			// can be created if the type has a default factory function
-			if( !ot->GetEngine()->GetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE) )
+			if( !ti->GetEngine()->GetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE) )
 			{
 				// Verify that there is a default factory
 				for( asUINT n = 0; n < subtype->GetFactoryCount(); n++ )
@@ -243,7 +188,8 @@ static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageColl
 			if( !found )
 			{
 				// No default factory
-				ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default factory");
+				// TODO: Should format the message to give the name of the subtype for better understanding
+				ti->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default factory");
 				return false;
 			}
 		}
@@ -266,7 +212,7 @@ static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageColl
 		// If it is possible to determine that the handle cannot refer to an object type
 		// that can potentially form a circular reference with the array then it is not 
 		// necessary to make the array garbage collected.
-		asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId);
+		asITypeInfo *subtype = ti->GetEngine()->GetTypeInfoById(typeId);
 		asDWORD flags = subtype->GetFlags();
 		if( !(flags & asOBJ_GC) )
 		{
@@ -317,7 +263,7 @@ static void RegisterScriptArray_Native(asIScriptEngine *engine)
 	UNUSED_VAR(r);
 
 	// Register the object type user data clean up
-	engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE);
+	engine->SetTypeInfoUserDataCleanupCallback(CleanupTypeInfoArrayCache, ARRAY_CACHE);
 
 	// Register the array type as a template
 	r = engine->RegisterObjectType("array<class T>", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 );
@@ -326,45 +272,54 @@ static void RegisterScriptArray_Native(asIScriptEngine *engine)
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback), asCALL_CDECL); assert( r >= 0 );
 
 	// Templates receive the object type as the first parameter. To the script writer this is hidden
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint, const T &in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT, void *), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint length)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint length, const T &in value)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, asUINT, void *), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
 
 	// Register the factory that will be used for initialization lists
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_LIST_FACTORY, "array<T>@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, void*), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_LIST_FACTORY, "array<T>@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, void*), CScriptArray*), asCALL_CDECL); assert( r >= 0 );
 
 	// The memory management methods
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL); assert( r >= 0 );
 
 	// The index operator returns the template subtype
-	r = engine->RegisterObjectMethod("array<T>", "T &opIndex(uint)", asMETHODPR(CScriptArray, At, (asUINT), void*), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "const T &opIndex(uint) const", asMETHODPR(CScriptArray, At, (asUINT) const, const void*), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "T &opIndex(uint index)", asMETHODPR(CScriptArray, At, (asUINT), void*), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "const T &opIndex(uint index) const", asMETHODPR(CScriptArray, At, (asUINT) const, const void*), asCALL_THISCALL); assert( r >= 0 );
 
 	// The assignment operator
 	r = engine->RegisterObjectMethod("array<T>", "array<T> &opAssign(const array<T>&in)", asMETHOD(CScriptArray, operator=), asCALL_THISCALL); assert( r >= 0 );
 
 	// Other methods
-	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void removeAt(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void insertLast(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint index, const T&in value)", asMETHODPR(CScriptArray, InsertAt, (asUINT, void *), void), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint index, const array<T>& arr)", asMETHODPR(CScriptArray, InsertAt, (asUINT, const CScriptArray &), void), asCALL_THISCALL); assert(r >= 0);
+	r = engine->RegisterObjectMethod("array<T>", "void insertLast(const T&in value)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert(r >= 0);
+	r = engine->RegisterObjectMethod("array<T>", "void removeAt(uint index)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert(r >= 0);
 	r = engine->RegisterObjectMethod("array<T>", "void removeLast()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void removeRange(uint start, uint count)", asMETHOD(CScriptArray, RemoveRange), asCALL_THISCALL); assert(r >= 0);
 	// TODO: Should length() and resize() be deprecated as the property accessors do the same thing?
 	r = engine->RegisterObjectMethod("array<T>", "uint length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void reserve(uint)", asMETHOD(CScriptArray, Reserve), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void resize(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void reserve(uint length)", asMETHOD(CScriptArray, Reserve), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void resize(uint length)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void sortAsc()", asMETHODPR(CScriptArray, SortAsc, (), void), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void sortAsc(uint, uint)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void sortAsc(uint startAt, uint count)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void sortDesc()", asMETHODPR(CScriptArray, SortDesc, (), void), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void sortDesc(uint, uint)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void sortDesc(uint startAt, uint count)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void reverse()", asMETHOD(CScriptArray, Reverse), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int find(const T&in) const", asMETHODPR(CScriptArray, Find, (void*) const, int), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int find(uint, const T&in) const", asMETHODPR(CScriptArray, Find, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int findByRef(const T&in) const", asMETHODPR(CScriptArray, FindByRef, (void*) const, int), asCALL_THISCALL); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int findByRef(uint, const T&in) const", asMETHODPR(CScriptArray, FindByRef, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 );
+	// The token 'if_handle_then_const' tells the engine that if the type T is a handle, then it should refer to a read-only object
+	r = engine->RegisterObjectMethod("array<T>", "int find(const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, Find, (void*) const, int), asCALL_THISCALL); assert( r >= 0 );
+	// TODO: It should be "int find(const T&in value, uint startAt = 0) const"
+	r = engine->RegisterObjectMethod("array<T>", "int find(uint startAt, const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, Find, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "int findByRef(const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, FindByRef, (void*) const, int), asCALL_THISCALL); assert( r >= 0 );
+	// TODO: It should be "int findByRef(const T&in value, uint startAt = 0) const"
+	r = engine->RegisterObjectMethod("array<T>", "int findByRef(uint startAt, const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, FindByRef, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "bool opEquals(const array<T>&in) const", asMETHOD(CScriptArray, operator==), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "bool isEmpty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 );
 
+	// Sort with callback for comparison
+	r = engine->RegisterFuncdef("bool array<T>::less(const T&in a, const T&in b)");
+	r = engine->RegisterObjectMethod("array<T>", "void sort(const less &in, uint startAt = 0, uint count = uint(-1))", asMETHODPR(CScriptArray, Sort, (asIScriptFunction*, asUINT, asUINT), void), asCALL_THISCALL); assert(r >= 0);
+
 	// Register virtual properties
 	r = engine->RegisterObjectMethod("array<T>", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void set_length(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 );
@@ -386,7 +341,8 @@ static void RegisterScriptArray_Native(asIScriptEngine *engine)
 	// Same as removeLast
 	r = engine->RegisterObjectMethod("array<T>", "void pop_back()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 );
 	// Same as insertAt
-	r = engine->RegisterObjectMethod("array<T>", "void insert(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void insert(uint index, const T&in value)", asMETHODPR(CScriptArray, InsertAt, (asUINT, void *), void), asCALL_THISCALL); assert(r >= 0);
+	r = engine->RegisterObjectMethod("array<T>", "void insert(uint index, const array<T>& arr)", asMETHODPR(CScriptArray, InsertAt, (asUINT, const CScriptArray &), void), asCALL_THISCALL); assert(r >= 0);
 	// Same as removeAt
 	r = engine->RegisterObjectMethod("array<T>", "void erase(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 );
 #endif
@@ -408,17 +364,20 @@ CScriptArray &CScriptArray::operator=(const CScriptArray &other)
 	return *this;
 }
 
-CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
+CScriptArray::CScriptArray(asITypeInfo *ti, void *buf)
 {
+	// The object type should be the template instance of the array
+	assert( ti && string(ti->GetName()) == "array" );
+
 	refCount = 1;
 	gcFlag = false;
-	objType = ot;
+	objType = ti;
 	objType->AddRef();
 	buffer = 0;
 
 	Precache();
 
-	asIScriptEngine *engine = ot->GetEngine();
+	asIScriptEngine *engine = ti->GetEngine();
 
 	// Determine element size
 	if( subTypeId & asTYPEID_MASK_OBJECT )
@@ -437,7 +396,7 @@ CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
 	}
 
 	// Copy the values of the array elements from the buffer
-	if( (ot->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 )
+	if( (ti->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 )
 	{
 		CreateBuffer(&buffer, length);
 
@@ -445,7 +404,7 @@ CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
 		if( length > 0 )
 			memcpy(At(0), (((asUINT*)buf)+1), length * elementSize);
 	}
-	else if( ot->GetSubTypeId() & asTYPEID_OBJHANDLE )
+	else if( ti->GetSubTypeId() & asTYPEID_OBJHANDLE )
 	{
 		CreateBuffer(&buffer, length);
 
@@ -459,7 +418,7 @@ CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
 		// its references too
 		memset((((asUINT*)buf)+1), 0, length * elementSize);
 	}
-	else if( ot->GetSubType()->GetFlags() & asOBJ_REF )
+	else if( ti->GetSubType()->GetFlags() & asOBJ_REF )
 	{
 		// Only allocate the buffer, but not the objects
 		subTypeId |= asTYPEID_OBJHANDLE;
@@ -488,8 +447,8 @@ CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
 		{
 			void *obj = At(n);
 			asBYTE *srcObj = (asBYTE*)buf;
-			srcObj += 4 + n*ot->GetSubType()->GetSize();
-			engine->AssignScriptObject(obj, srcObj, ot->GetSubType());
+			srcObj += 4 + n*ti->GetSubType()->GetSize();
+			engine->AssignScriptObject(obj, srcObj, ti->GetSubType());
 		}
 	}
 
@@ -498,11 +457,14 @@ CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
 		objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType);
 }
 
-CScriptArray::CScriptArray(asUINT length, asIObjectType *ot)
+CScriptArray::CScriptArray(asUINT length, asITypeInfo *ti)
 {
+	// The object type should be the template instance of the array
+	assert( ti && string(ti->GetName()) == "array" );
+
 	refCount = 1;
 	gcFlag = false;
-	objType = ot;
+	objType = ti;
 	objType->AddRef();
 	buffer = 0;
 
@@ -549,11 +511,14 @@ CScriptArray::CScriptArray(const CScriptArray &other)
 	*this = other;
 }
 
-CScriptArray::CScriptArray(asUINT length, void *defVal, asIObjectType *ot)
+CScriptArray::CScriptArray(asUINT length, void *defVal, asITypeInfo *ti)
 {
+	// The object type should be the template instance of the array
+	assert( ti && string(ti->GetName()) == "array" );
+
 	refCount = 1;
 	gcFlag = false;
-	objType = ot;
+	objType = ti;
 	objType->AddRef();
 	buffer = 0;
 
@@ -662,9 +627,8 @@ void CScriptArray::Reserve(asUINT maxElements)
 		return;
 	}
 
-	// TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves
-	//       This should really be using the objects copy/move constructor to copy each object
-	//       to the new location. It would most likely be a hit on the performance though.
+	// As objects in arrays of objects are not stored inline, it is safe to use memcpy here
+	// since we're just copying the pointers to objects and not the actual objects.
 	memcpy(newBuffer->data, buffer->data, buffer->numElements*elementSize);
 
 	// Release the old buffer
@@ -681,6 +645,34 @@ void CScriptArray::Resize(asUINT numElements)
 	Resize((int)numElements - (int)buffer->numElements, (asUINT)-1);
 }
 
+void CScriptArray::RemoveRange(asUINT start, asUINT count)
+{
+	if (count == 0)
+		return;
+
+	if( buffer == 0 || start > buffer->numElements )
+	{
+		// If this is called from a script we raise a script exception
+		asIScriptContext *ctx = asGetActiveContext();
+		if (ctx)
+			ctx->SetException("Index out of bounds");
+		return;
+	}
+
+	// Cap count to the end of the array
+	if (start + count > buffer->numElements)
+		count = buffer->numElements - start;
+
+	// Destroy the elements that are being removed
+	Destruct(buffer, start, start + count);
+
+	// Compact the elements
+	// As objects in arrays of objects are not stored inline, it is safe to use memmove here
+	// since we're just copying the pointers to objects and not the actual objects.
+	memmove(buffer->data + start*elementSize, buffer->data + (start + count)*elementSize, (buffer->numElements - start - count)*elementSize);
+	buffer->numElements -= count;
+}
+
 // Internal
 void CScriptArray::Resize(int delta, asUINT at)
 {
@@ -721,9 +713,8 @@ void CScriptArray::Resize(int delta, asUINT at)
 			return;
 		}
 
-		// TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves
-		//       This should really be using the objects copy/move constructor to copy each object
-		//       to the new location. It would most likely be a hit on the performance though.
+		// As objects in arrays of objects are not stored inline, it is safe to use memcpy here
+		// since we're just copying the pointers to objects and not the actual objects.
 		memcpy(newBuffer->data, buffer->data, at*elementSize);
 		if( at < buffer->numElements )
 			memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize);
@@ -739,17 +730,15 @@ void CScriptArray::Resize(int delta, asUINT at)
 	else if( delta < 0 )
 	{
 		Destruct(buffer, at, at-delta);
-		// TODO: memmove assumes the objects in the array doesn't hold pointers to themselves
-		//       This should really be using the objects copy/move constructor to copy each object
-		//       to the new location. It would most likely be a hit on the performance though.
+		// As objects in arrays of objects are not stored inline, it is safe to use memmove here
+		// since we're just copying the pointers to objects and not the actual objects.
 		memmove(buffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements - (at-delta))*elementSize);
 		buffer->numElements += delta;
 	}
 	else
 	{
-		// TODO: memmove assumes the objects in the array doesn't hold pointers to themselves
-		//       This should really be using the objects copy/move constructor to copy each object
-		//       to the new location. It would most likely be a hit on the performance though.
+		// As objects in arrays of objects are not stored inline, it is safe to use memmove here
+		// since we're just copying the pointers to objects and not the actual objects.
 		memmove(buffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements - at)*elementSize);
 		Construct(buffer, at, at+delta);
 		buffer->numElements += delta;
@@ -779,7 +768,7 @@ bool CScriptArray::CheckMaxSize(asUINT numElements)
 	return true;
 }
 
-asIObjectType *CScriptArray::GetArrayObjectType() const
+asITypeInfo *CScriptArray::GetArrayObjectType() const
 {
 	return objType;
 }
@@ -812,6 +801,61 @@ void CScriptArray::InsertAt(asUINT index, void *value)
 	SetValue(index, value);
 }
 
+void CScriptArray::InsertAt(asUINT index, const CScriptArray &arr)
+{
+	if (index > buffer->numElements)
+	{
+		asIScriptContext *ctx = asGetActiveContext();
+		if (ctx)
+			ctx->SetException("Index out of bounds");
+		return;
+	}
+
+	if (objType != arr.objType)
+	{
+		// This shouldn't really be possible to happen when
+		// called from a script, but let's check for it anyway
+		asIScriptContext *ctx = asGetActiveContext();
+		if (ctx)
+			ctx->SetException("Mismatching array types");
+		return;
+	}
+
+	asUINT elements = arr.GetSize();
+	Resize(elements, index);
+	if (&arr != this)
+	{
+		for (asUINT n = 0; n < arr.GetSize(); n++)
+		{
+			// This const cast is allowed, since we know the
+			// value will only be used to make a copy of it
+			void *value = const_cast<void*>(arr.At(n));
+			SetValue(index + n, value);
+		}
+	}
+	else
+	{
+		// The array that is being inserted is the same as this one.
+		// So we should iterate over the elements before the index,
+		// and then the elements after
+		for (asUINT n = 0; n < index; n++)
+		{
+			// This const cast is allowed, since we know the
+			// value will only be used to make a copy of it
+			void *value = const_cast<void*>(arr.At(n));
+			SetValue(index + n, value);
+		}
+
+		for (asUINT n = index + elements, m = 0; n < arr.GetSize(); n++, m++)
+		{
+			// This const cast is allowed, since we know the
+			// value will only be used to make a copy of it
+			void *value = const_cast<void*>(arr.At(n));
+			SetValue(index + index + m, value);
+		}
+	}
+}
+
 void CScriptArray::InsertLast(void *value)
 {
 	InsertAt(buffer->numElements, value);
@@ -859,6 +903,11 @@ void *CScriptArray::At(asUINT index)
 	return const_cast<void*>(const_cast<const CScriptArray *>(this)->At(index));
 }
 
+void *CScriptArray::GetBuffer()
+{
+	return buffer->data;
+}
+
 
 // internal
 void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements)
@@ -899,7 +948,7 @@ void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end)
 		void **d = (void**)(buf->data + start * sizeof(void*));
 
 		asIScriptEngine *engine = objType->GetEngine();
-		asIObjectType *subType = objType->GetSubType();
+		asITypeInfo *subType = objType->GetSubType();
 
 		for( ; d < max; d++ )
 		{
@@ -975,6 +1024,8 @@ bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext
 	}
 	else
 	{
+		int r = 0;
+
 		if( subTypeId & asTYPEID_OBJHANDLE )
 		{
 			// Allow sort to work even if the array contains null handles
@@ -986,7 +1037,7 @@ bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext
 		if( cache && cache->cmpFunc )
 		{
 			// TODO: Add proper error handling
-            int r = ctx->Prepare(cache->cmpFunc); assert(r >= 0);
+			r = ctx->Prepare(cache->cmpFunc); assert(r >= 0);
 
 			if( subTypeId & asTYPEID_OBJHANDLE )
 			{
@@ -1219,7 +1270,7 @@ int CScriptArray::Find(asUINT startAt, void *value) const
 		if( !cache || (cache->cmpFunc == 0 && cache->eqFunc == 0) )
 		{
 			asIScriptContext *ctx = asGetActiveContext();
-			asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
+			asITypeInfo* subType = objType->GetEngine()->GetTypeInfoById(subTypeId);
 
 			// Throw an exception
 			if( ctx )
@@ -1302,6 +1353,8 @@ int CScriptArray::Find(asUINT startAt, void *value) const
 
 // internal
 // Copy object handle or primitive value
+// Even in arrays of objects the objects are allocated on 
+// the heap and the array stores the pointers to the objects
 void CScriptArray::Copy(void *dst, void *src)
 {
 	memcpy(dst, src, elementSize);
@@ -1317,17 +1370,17 @@ void *CScriptArray::GetArrayItemPointer(int index)
 
 // internal
 // Return pointer to data in buffer (object or primitive)
-void *CScriptArray::GetDataPointer(void *buffer)
+void *CScriptArray::GetDataPointer(void *buf)
 {
 	if ((subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) )
 	{
 		// Real address of object
-		return reinterpret_cast<void*>(*(size_t*)buffer);
+		return reinterpret_cast<void*>(*(size_t*)buf);
 	}
 	else
 	{
 		// Primitive is just a raw data
-		return buffer;
+		return buf;
 	}
 }
 
@@ -1367,7 +1420,7 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc)
 		if( !cache || cache->cmpFunc == 0 )
 		{
 			asIScriptContext *ctx = asGetActiveContext();
-			asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
+			asITypeInfo* subType = objType->GetEngine()->GetTypeInfoById(subTypeId);
 
 			// Throw an exception
 			if( ctx )
@@ -1434,10 +1487,7 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc)
 		}
 		if( cmpContext == 0 )
 		{
-			// TODO: Ideally this context would be retrieved from a pool, so we don't have to
-			//       create a new one everytime. We could keep a context with the array object
-			//       but that would consume a lot of resources as each context is quite heavy.
-			cmpContext = objType->GetEngine()->CreateContext();
+			cmpContext = objType->GetEngine()->RequestContext();
 		}
 	}
 
@@ -1467,7 +1517,88 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc)
 				cmpContext->Abort();
 		}
 		else
-			cmpContext->Release();
+			objType->GetEngine()->ReturnContext(cmpContext);
+	}
+}
+
+// Sort with script callback for comparing elements
+void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count)
+{
+	// No need to sort
+	if (count < 2)
+		return;
+
+	// Check if we could access invalid item while sorting
+	asUINT start = startAt;
+	asUINT end = asQWORD(startAt) + asQWORD(count) >= (asQWORD(1)<<32) ? 0xFFFFFFFF : startAt + count;
+	if (end > buffer->numElements)
+		end = buffer->numElements;
+
+	if (start >= buffer->numElements)
+	{
+		asIScriptContext *ctx = asGetActiveContext();
+
+		// Throw an exception
+		if (ctx)
+			ctx->SetException("Index out of bounds");
+
+		return;
+	}
+
+	asBYTE tmp[16];
+	asIScriptContext *cmpContext = 0;
+	bool isNested = false;
+
+	// Try to reuse the active context
+	cmpContext = asGetActiveContext();
+	if (cmpContext)
+	{
+		if (cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0)
+			isNested = true;
+		else
+			cmpContext = 0;
+	}
+	if (cmpContext == 0)
+		cmpContext = objType->GetEngine()->RequestContext();
+
+	// Insertion sort
+	for (asUINT i = start + 1; i < end; i++)
+	{
+		Copy(tmp, GetArrayItemPointer(i));
+
+		asUINT j = i - 1;
+
+		while (j != 0xFFFFFFFF && j >= start )
+		{
+			cmpContext->Prepare(func);
+			cmpContext->SetArgAddress(0, GetDataPointer(tmp));
+			cmpContext->SetArgAddress(1, At(j));
+			int r = cmpContext->Execute();
+			if (r != asEXECUTION_FINISHED)
+				break;
+			if (*(bool*)(cmpContext->GetAddressOfReturnValue()))
+			{
+				Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j));
+				j--;
+			}
+			else
+				break;
+		}
+
+		Copy(GetArrayItemPointer(j + 1), tmp);
+	}
+
+	if (cmpContext)
+	{
+		if (isNested)
+		{
+			asEContextState state = cmpContext->GetState();
+			cmpContext->PopState();
+			if (state == asEXECUTION_ABORTED)
+				cmpContext->Abort();
+		}
+		else
+			objType->GetEngine()->ReturnContext(cmpContext);
 	}
 }
 
@@ -1510,7 +1641,7 @@ void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src)
 				void **d   = (void**)dst->data;
 				void **s   = (void**)src->data;
 
-				asIObjectType *subType = objType->GetSubType();
+				asITypeInfo *subType = objType->GetSubType();
 				for( ; d < max; d++, s++ )
 					engine->AssignScriptObject(*d, *s, subType);
 			}
@@ -1561,7 +1692,7 @@ void CScriptArray::Precache()
 	// If the sub type is a handle to const, then the methods must be const too
 	bool mustBeConst = (subTypeId & asTYPEID_HANDLETOCONST) ? true : false;
 
-	asIObjectType *subType = objType->GetEngine()->GetObjectTypeById(subTypeId);
+	asITypeInfo *subType = objType->GetEngine()->GetTypeInfoById(subTypeId);
 	if( subType )
 	{
 		for( asUINT i = 0; i < subType->GetMethodCount(); i++ )
@@ -1710,41 +1841,41 @@ bool CScriptArray::GetFlag()
 
 static void ScriptArrayFactory_Generic(asIScriptGeneric *gen)
 {
-	asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
+	asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0);
 
-	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot);
+	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti);
 }
 
 static void ScriptArrayFactory2_Generic(asIScriptGeneric *gen)
 {
-	asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
+	asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0);
 	asUINT length = gen->GetArgDWord(1);
 
-	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length);
+	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, length);
 }
 
 static void ScriptArrayListFactory_Generic(asIScriptGeneric *gen)
 {
-	asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
+	asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0);
 	void *buf = gen->GetArgAddress(1);
 
-	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, buf);
+	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, buf);
 }
 
 static void ScriptArrayFactoryDefVal_Generic(asIScriptGeneric *gen)
 {
-	asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
+	asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0);
 	asUINT length = gen->GetArgDWord(1);
 	void *defVal = gen->GetArgAddress(2);
 
-	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length, defVal);
+	*reinterpret_cast<CScriptArray**>(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, length, defVal);
 }
 
 static void ScriptArrayTemplateCallback_Generic(asIScriptGeneric *gen)
 {
-	asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0);
+	asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0);
 	bool *dontGarbageCollect = *(bool**)gen->GetAddressOfArg(1);
-	*reinterpret_cast<bool*>(gen->GetAddressOfReturnLocation()) = ScriptArrayTemplateCallback(ot, *dontGarbageCollect);
+	*reinterpret_cast<bool*>(gen->GetAddressOfReturnLocation()) = ScriptArrayTemplateCallback(ti, *dontGarbageCollect);
 }
 
 static void ScriptArrayAssignment_Generic(asIScriptGeneric *gen)
@@ -1808,6 +1939,14 @@ static void ScriptArrayInsertAt_Generic(asIScriptGeneric *gen)
 	self->InsertAt(index, value);
 }
 
+static void ScriptArrayInsertAtArray_Generic(asIScriptGeneric *gen)
+{
+	asUINT index = gen->GetArgDWord(0);
+	CScriptArray *array = (CScriptArray*)gen->GetArgAddress(1);
+	CScriptArray *self = (CScriptArray*)gen->GetObject();
+	self->InsertAt(index, *array);
+}
+
 static void ScriptArrayRemoveAt_Generic(asIScriptGeneric *gen)
 {
 	asUINT index = gen->GetArgDWord(0);
@@ -1815,6 +1954,14 @@ static void ScriptArrayRemoveAt_Generic(asIScriptGeneric *gen)
 	self->RemoveAt(index);
 }
 
+static void ScriptArrayRemoveRange_Generic(asIScriptGeneric *gen)
+{
+	asUINT start = gen->GetArgDWord(0);
+	asUINT count = gen->GetArgDWord(1);
+	CScriptArray *self = (CScriptArray*)gen->GetObject();
+	self->RemoveRange(start, count);
+}
+
 static void ScriptArrayInsertLast_Generic(asIScriptGeneric *gen)
 {
 	void *value = gen->GetArgAddress(0);
@@ -1890,6 +2037,15 @@ static void ScriptArraySortDesc2_Generic(asIScriptGeneric *gen)
 	self->SortDesc(index, count);
 }
 
+static void ScriptArraySortCallback_Generic(asIScriptGeneric *gen)
+{
+	asIScriptFunction *callback = (asIScriptFunction*)gen->GetArgAddress(0);
+	asUINT startAt = gen->GetArgDWord(1);
+	asUINT count = gen->GetArgDWord(2);
+	CScriptArray *self = (CScriptArray*)gen->GetObject();
+	self->Sort(callback, startAt, count);
+}
+
 static void ScriptArrayAddRef_Generic(asIScriptGeneric *gen)
 {
 	CScriptArray *self = (CScriptArray*)gen->GetObject();
@@ -1939,39 +2095,43 @@ static void RegisterScriptArray_Generic(asIScriptEngine *engine)
 	int r = 0;
 	UNUSED_VAR(r);
 
-	engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE);
+	engine->SetTypeInfoUserDataCleanupCallback(CleanupTypeInfoArrayCache, ARRAY_CACHE);
 
 	r = engine->RegisterObjectType("array<class T>", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 );
 
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in)", asFUNCTION(ScriptArrayFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint, const T &in)", asFUNCTION(ScriptArrayFactoryDefVal_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint length)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_FACTORY, "array<T>@ f(int&in, uint length, const T &in value)", asFUNCTION(ScriptArrayFactoryDefVal_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_LIST_FACTORY, "array<T>@ f(int&in, int&in) {repeat T}", asFUNCTION(ScriptArrayListFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptArrayAddRef_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptArrayRelease_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "T &opIndex(uint)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "const T &opIndex(uint) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "T &opIndex(uint index)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "const T &opIndex(uint index) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "array<T> &opAssign(const array<T>&in)", asFUNCTION(ScriptArrayAssignment_Generic), asCALL_GENERIC); assert( r >= 0 );
 
-	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint, const T&in)", asFUNCTION(ScriptArrayInsertAt_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void removeAt(uint)", asFUNCTION(ScriptArrayRemoveAt_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void insertLast(const T&in)", asFUNCTION(ScriptArrayInsertLast_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint index, const T&in value)", asFUNCTION(ScriptArrayInsertAt_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void insertAt(uint index, const array<T>& arr)", asFUNCTION(ScriptArrayInsertAtArray_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("array<T>", "void insertLast(const T&in value)", asFUNCTION(ScriptArrayInsertLast_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("array<T>", "void removeAt(uint index)", asFUNCTION(ScriptArrayRemoveAt_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void removeLast()", asFUNCTION(ScriptArrayRemoveLast_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void removeRange(uint start, uint count)", asFUNCTION(ScriptArrayRemoveRange_Generic), asCALL_GENERIC); assert(r >= 0);
 	r = engine->RegisterObjectMethod("array<T>", "uint length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void reserve(uint)", asFUNCTION(ScriptArrayReserve_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void resize(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void reserve(uint length)", asFUNCTION(ScriptArrayReserve_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void resize(uint length)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void sortAsc()", asFUNCTION(ScriptArraySortAsc_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void sortAsc(uint, uint)", asFUNCTION(ScriptArraySortAsc2_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void sortAsc(uint startAt, uint count)", asFUNCTION(ScriptArraySortAsc2_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void sortDesc()", asFUNCTION(ScriptArraySortDesc_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "void sortDesc(uint, uint)", asFUNCTION(ScriptArraySortDesc2_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "void sortDesc(uint startAt, uint count)", asFUNCTION(ScriptArraySortDesc2_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void reverse()", asFUNCTION(ScriptArrayReverse_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int find(const T&in) const", asFUNCTION(ScriptArrayFind_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int find(uint, const T&in) const", asFUNCTION(ScriptArrayFind2_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int findByRef(const T&in) const", asFUNCTION(ScriptArrayFindByRef_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("array<T>", "int findByRef(uint, const T&in) const", asFUNCTION(ScriptArrayFindByRef2_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "int find(const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFind_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "int find(uint startAt, const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFind2_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "int findByRef(const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFindByRef_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("array<T>", "int findByRef(uint startAt, const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFindByRef2_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "bool opEquals(const array<T>&in) const", asFUNCTION(ScriptArrayEquals_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "bool isEmpty() const", asFUNCTION(ScriptArrayIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterFuncdef("bool array<T>::less(const T&in a, const T&in b)");
+	r = engine->RegisterObjectMethod("array<T>", "void sort(const less &in, uint startAt = 0, uint count = uint(-1))", asFUNCTION(ScriptArraySortCallback_Generic), asCALL_GENERIC); assert(r >= 0);
 	r = engine->RegisterObjectMethod("array<T>", "uint get_length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("array<T>", "void set_length(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectBehaviour("array<T>", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptArrayGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 );
diff --git a/src/scriptengine/scriptarray.hpp b/src/scriptengine/scriptarray.hpp
index a1c0a0a1d..e6eb2783a 100644
--- a/src/scriptengine/scriptarray.hpp
+++ b/src/scriptengine/scriptarray.hpp
@@ -29,19 +29,19 @@ public:
 	static void SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc);
 
 	// Factory functions
-	static CScriptArray *Create(asIObjectType *ot);
-	static CScriptArray *Create(asIObjectType *ot, asUINT length);
-	static CScriptArray *Create(asIObjectType *ot, asUINT length, void *defaultValue);
-	static CScriptArray *Create(asIObjectType *ot, void *listBuffer);
+	static CScriptArray *Create(asITypeInfo *ot);
+	static CScriptArray *Create(asITypeInfo *ot, asUINT length);
+	static CScriptArray *Create(asITypeInfo *ot, asUINT length, void *defaultValue);
+	static CScriptArray *Create(asITypeInfo *ot, void *listBuffer);
 
 	// Memory management
 	void AddRef() const;
 	void Release() const;
 
 	// Type information
-	asIObjectType *GetArrayObjectType() const;
-	int            GetArrayTypeId() const;
-	int            GetElementTypeId() const;
+	asITypeInfo *GetArrayObjectType() const;
+	int          GetArrayTypeId() const;
+	int          GetElementTypeId() const;
 
 	// Get the current size
 	asUINT GetSize() const;
@@ -73,20 +73,26 @@ public:
 
 	// Array manipulation
 	void InsertAt(asUINT index, void *value);
-	void RemoveAt(asUINT index);
+	void InsertAt(asUINT index, const CScriptArray &arr);
 	void InsertLast(void *value);
+	void RemoveAt(asUINT index);
 	void RemoveLast();
+	void RemoveRange(asUINT start, asUINT count);
 	void SortAsc();
 	void SortDesc();
 	void SortAsc(asUINT startAt, asUINT count);
 	void SortDesc(asUINT startAt, asUINT count);
 	void Sort(asUINT startAt, asUINT count, bool asc);
+	void Sort(asIScriptFunction *less, asUINT startAt, asUINT count);
 	void Reverse();
 	int  Find(void *value) const;
 	int  Find(asUINT startAt, void *value) const;
 	int  FindByRef(void *ref) const;
 	int  FindByRef(asUINT startAt, void *ref) const;
 
+	// Return the address of internal buffer for direct manipulation of elements
+	void *GetBuffer();
+
 	// GC methods
 	int  GetRefCount();
 	void SetFlag();
@@ -95,17 +101,17 @@ public:
 	void ReleaseAllHandles(asIScriptEngine *engine);
 
 protected:
-	mutable int       refCount;
-	mutable bool      gcFlag;
-	asIObjectType    *objType;
-	SArrayBuffer     *buffer;
-	int               elementSize;
-	int               subTypeId;
+	mutable int     refCount;
+	mutable bool    gcFlag;
+	asITypeInfo    *objType;
+	SArrayBuffer   *buffer;
+	int             elementSize;
+	int             subTypeId;
 
 	// Constructors
-	CScriptArray(asIObjectType *ot, void *initBuf); // Called from script when initialized with list
-	CScriptArray(asUINT length, asIObjectType *ot);
-	CScriptArray(asUINT length, void *defVal, asIObjectType *ot);
+	CScriptArray(asITypeInfo *ot, void *initBuf); // Called from script when initialized with list
+	CScriptArray(asUINT length, asITypeInfo *ot);
+	CScriptArray(asUINT length, void *defVal, asITypeInfo *ot);
 	CScriptArray(const CScriptArray &other);
 	virtual ~CScriptArray();
 
diff --git a/src/scriptengine/scriptstdstring.cpp b/src/scriptengine/scriptstdstring.cpp
index 381a78cc1..4da068109 100644
--- a/src/scriptengine/scriptstdstring.cpp
+++ b/src/scriptengine/scriptstdstring.cpp
@@ -1,33 +1,3 @@
-/*
-AngelCode Scripting Library
-Copyright (c) 2003-2015 Andreas Jonsson
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you
-must not claim that you wrote the original software. If you use
-this software in a product, an acknowledgment in the product
-documentation would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-
-The original version of this library can be located at:
-http://www.angelcode.com/angelscript/
-
-Andreas Jonsson
-andreas@angelcode.com
-*/
-
 #include "scriptstdstring.hpp"
 #include <assert.h> // assert()
 #include <sstream>  // std::stringstream
@@ -37,119 +7,85 @@ andreas@angelcode.com
 #ifndef __psp2__
 	#include <locale.h> // setlocale()
 #endif
-#include <map>      // std::map
 
 using namespace std;
 
-BEGIN_AS_NAMESPACE
-
 // This macro is used to avoid warnings about unused variables.
 // Usually where the variables are only used in debug mode.
 #define UNUSED_VAR(x) (void)(x)
 
-#if AS_USE_STRINGPOOL == 1
-
-// By keeping the literal strings in a pool the application
-// performance is improved as there are less string copies created.
-
-// The string pool will be kept as user data in the engine. We'll
-// need a specific type to identify the string pool user data.
-// We just define a number here that we assume nobody else is using for
-// object type user data. The add-ons have reserved the numbers 1000
-// through 1999 for this purpose, so we should be fine.
-const asPWORD STRING_POOL = 1001;
-
-// This global static variable is placed here rather than locally within the
-// StringFactory, due to memory leak detectors that don't see the deallocation
-// of global variables. By placing the variable globally it will be initialized
-// before the memory leak detector starts, thus it won't report the missing
-// deallocation. An example of this the Marmalade leak detector initialized with
-// IwGxInit() and finished with IwGxTerminate().
-static const string emptyString;
+#ifdef AS_CAN_USE_CPP11
+// The string factory doesn't need to keep a specific order in the
+// cache, so the unordered_map is faster than the ordinary map
+#include <unordered_map>  // std::unordered_map
+BEGIN_AS_NAMESPACE
+typedef unordered_map<string, int> map_t;
+END_AS_NAMESPACE
+#else
+#include <map>      // std::map
+BEGIN_AS_NAMESPACE
+typedef map<string, int> map_t;
+END_AS_NAMESPACE
+#endif
 
-static const string &StringFactory(asUINT length, const char *s)
+class CStdStringFactory : public asIStringFactory
 {
-	// Each engine instance has its own string pool
-	asIScriptContext *ctx = asGetActiveContext();
-	if( ctx == 0 )
+public:
+	CStdStringFactory() {}
+	~CStdStringFactory() 
 	{
-		// The string factory can only be called from a script
-		assert( ctx );
-		return emptyString;
+		// The script engine must release each string 
+		// constant that it has requested
+		assert(stringCache.size() == 0);
 	}
-	asIScriptEngine *engine = ctx->GetEngine();
 
-	// TODO: runtime optimize: Use unordered_map if C++11 is supported, i.e. MSVC10+, gcc 4.?+
-	map<const char *, string> *pool = reinterpret_cast< map<const char *, string>* >(engine->GetUserData(STRING_POOL));
+	const void *GetStringConstant(const char *data, asUINT length)
+	{
+		string str(data, length);
+		map_t::iterator it = stringCache.find(str);
+		if (it != stringCache.end())
+			it->second++;
+		else
+			it = stringCache.insert(map_t::value_type(str, 1)).first;
+
+		return reinterpret_cast<const void*>(&it->first);
+	}
 
-	if( !pool )
+	int  ReleaseStringConstant(const void *str)
 	{
-		// The string pool hasn't been created yet, so we'll create it now
-		asAcquireExclusiveLock();
+		if (str == 0)
+			return asERROR;
 
-		// Make sure the string pool wasn't created while we were waiting for the lock
-		pool = reinterpret_cast< map<const char *, string>* >(engine->GetUserData(STRING_POOL));
-		if( !pool )
-		{
-			#if defined(__S3E__)
-			pool = new map<const char *, string>;
-			#else
-			pool = new (nothrow) map<const char *, string>;
-			#endif
-			if( pool == 0 )
-			{
-				ctx->SetException("Out of memory");
-				asReleaseExclusiveLock();
-				return emptyString;
-			}
-			engine->SetUserData(pool, STRING_POOL);
-		}
+		map_t::iterator it = stringCache.find(*reinterpret_cast<const string*>(str));
+		if (it == stringCache.end())
+			return asERROR;
 
-		asReleaseExclusiveLock();
+		it->second--;
+		if (it->second == 0)
+			stringCache.erase(it);
+		return asSUCCESS;
 	}
 
-	// We can't let other threads modify the pool while we query it
-	asAcquireSharedLock();
-
-	// First check if a string object hasn't been created already
-	map<const char *, string>::iterator it;
-	it = pool->find(s);
-	if( it != pool->end() )
+	int  GetRawStringData(const void *str, char *data, asUINT *length) const
 	{
-		asReleaseSharedLock();
-		return it->second;
-	}
+		if (str == 0)
+			return asERROR;
 
-	asReleaseSharedLock();
+		if (length)
+			*length = (asUINT)reinterpret_cast<const string*>(str)->length();
 
-	// Acquire an exclusive lock so we can add the new string to the pool
-	asAcquireExclusiveLock();
+		if (data)
+			memcpy(data, reinterpret_cast<const string*>(str)->c_str(), reinterpret_cast<const string*>(str)->length());
 
-	// Make sure the string wasn't created while we were waiting for the exclusive lock
-	it = pool->find(s);
-	if( it == pool->end() )
-	{
-		// Create a new string object
-		it = pool->insert(map<const char *, string>::value_type(s, string(s, length))).first;
+		return asSUCCESS;
 	}
 
-	asReleaseExclusiveLock();
-	return it->second;
-}
+	// TODO: Make sure the access to the string cache is thread safe
+	map_t stringCache;
+};
 
-static void CleanupEngineStringPool(asIScriptEngine *engine)
-{
-	map<const char *, string> *pool = reinterpret_cast< map<const char *, string>* >(engine->GetUserData(STRING_POOL));
-	if( pool )
-		delete pool;
-}
+static CStdStringFactory stringFactory;
 
-#else
-static string StringFactory(asUINT length, const char *s)
-{
-	return string(s, length);
-}
-#endif
 
 static void ConstructString(string *thisPointer)
 {
@@ -371,7 +307,53 @@ static int StringCmp(const string &a, const string &b)
 static int StringFindFirst(const string &sub, asUINT start, const string &str)
 {
 	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
-	return (int)str.find(sub, start);
+	return (int)str.find(sub, (size_t)(start < 0 ? string::npos : start));
+}
+
+// This function returns the index of the first position where the one of the bytes in substring
+// exists in the input string. If the characters in the substring doesn't exist in the input
+// string -1 is returned.
+//
+// AngelScript signature:
+// int string::findFirstOf(const string &in sub, uint start = 0) const
+static int StringFindFirstOf(const string &sub, asUINT start, const string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	return (int)str.find_first_of(sub, (size_t)(start < 0 ? string::npos : start));
+}
+
+// This function returns the index of the last position where the one of the bytes in substring
+// exists in the input string. If the characters in the substring doesn't exist in the input
+// string -1 is returned.
+//
+// AngelScript signature:
+// int string::findLastOf(const string &in sub, uint start = -1) const
+static int StringFindLastOf(const string &sub, asUINT start, const string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	return (int)str.find_last_of(sub, (size_t)(start < 0 ? string::npos : start));
+}
+
+// This function returns the index of the first position where a byte other than those in substring
+// exists in the input string. If none is found -1 is returned.
+//
+// AngelScript signature:
+// int string::findFirstNotOf(const string &in sub, uint start = 0) const
+static int StringFindFirstNotOf(const string &sub, asUINT start, const string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	return (int)str.find_first_not_of(sub, (size_t)(start < 0 ? string::npos : start));
+}
+
+// This function returns the index of the last position where a byte other than those in substring
+// exists in the input string. If none is found -1 is returned.
+//
+// AngelScript signature:
+// int string::findLastNotOf(const string &in sub, uint start = -1) const
+static int StringFindLastNotOf(const string &sub, asUINT start, const string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	return (int)str.find_last_of(sub, (size_t)(start < 0 ? string::npos : start));
 }
 
 // This function returns the index of the last position where the substring
@@ -383,9 +365,26 @@ static int StringFindFirst(const string &sub, asUINT start, const string &str)
 static int StringFindLast(const string &sub, int start, const string &str)
 {
 	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
-	return (int)str.rfind(sub, (size_t)start);
+	return (int)str.rfind(sub, (size_t)(start < 0 ? string::npos : start));
+}
+
+// AngelScript signature:
+// void string::insert(uint pos, const string &in other)
+static void StringInsert(unsigned int pos, const string &other, string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	str.insert(pos, other);
 }
 
+// AngelScript signature:
+// void string::erase(uint pos, int count = -1)
+static void StringErase(unsigned int pos, int count, string &str)
+{
+	// We don't register the method directly because the argument types change between 32bit and 64bit platforms
+	str.erase(pos, (size_t)(count < 0 ? string::npos : count));
+}
+
+
 // AngelScript signature:
 // uint string::length() const
 static asUINT StringLength(const string &str)
@@ -447,6 +446,50 @@ static string formatInt(asINT64 value, const string &options, asUINT width)
 	return buf;
 }
 
+// AngelScript signature:
+// string formatUInt(uint64 val, const string &in options, uint width)
+static string formatUInt(asQWORD value, const string &options, asUINT width)
+{
+	bool leftJustify = options.find("l") != string::npos;
+	bool padWithZero = options.find("0") != string::npos;
+	bool alwaysSign  = options.find("+") != string::npos;
+	bool spaceOnSign = options.find(" ") != string::npos;
+	bool hexSmall    = options.find("h") != string::npos;
+	bool hexLarge    = options.find("H") != string::npos;
+
+	string fmt = "%";
+	if( leftJustify ) fmt += "-";
+	if( alwaysSign ) fmt += "+";
+	if( spaceOnSign ) fmt += " ";
+	if( padWithZero ) fmt += "0";
+
+#ifdef _WIN32
+	fmt += "*I64";
+#else
+#ifdef _LP64
+	fmt += "*l";
+#else
+	fmt += "*ll";
+#endif
+#endif
+
+	if( hexSmall ) fmt += "x";
+	else if( hexLarge ) fmt += "X";
+	else fmt += "u";
+
+	string buf;
+	buf.resize(width+30);
+#if _MSC_VER >= 1400 && !defined(__S3E__)
+	// MSVC 8.0 / 2005 or newer
+	sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value);
+#else
+	sprintf(&buf[0], fmt.c_str(), width, value);
+#endif
+	buf.resize(strlen(&buf[0]));
+
+	return buf;
+}
+
 // AngelScript signature:
 // string formatFloat(double val, const string &in options, uint width, uint precision)
 static string formatFloat(double value, const string &options, asUINT width, asUINT precision)
@@ -540,15 +583,59 @@ static asINT64 parseInt(const string &val, asUINT base, asUINT *byteCount)
 	return res;
 }
 
+// AngelScript signature:
+// uint64 parseUInt(const string &in val, uint base = 10, uint &out byteCount = 0)
+static asQWORD parseUInt(const string &val, asUINT base, asUINT *byteCount)
+{
+	// Only accept base 10 and 16
+	if (base != 10 && base != 16)
+	{
+		if (byteCount) *byteCount = 0;
+		return 0;
+	}
+
+	const char *end = &val[0];
+
+	asQWORD res = 0;
+	if (base == 10)
+	{
+		while (*end >= '0' && *end <= '9')
+		{
+			res *= 10;
+			res += *end++ - '0';
+		}
+	}
+	else if (base == 16)
+	{
+		while ((*end >= '0' && *end <= '9') ||
+			(*end >= 'a' && *end <= 'f') ||
+			(*end >= 'A' && *end <= 'F'))
+		{
+			res *= 16;
+			if (*end >= '0' && *end <= '9')
+				res += *end++ - '0';
+			else if (*end >= 'a' && *end <= 'f')
+				res += *end++ - 'a' + 10;
+			else if (*end >= 'A' && *end <= 'F')
+				res += *end++ - 'A' + 10;
+		}
+	}
+
+	if (byteCount)
+		*byteCount = asUINT(size_t(end - val.c_str()));
+
+	return res;
+}
+
 // AngelScript signature:
 // double parseFloat(const string &in val, uint &out byteCount = 0)
 double parseFloat(const string &val, asUINT *byteCount)
 {
 	char *end;
 
-    // WinCE doesn't have setlocale. Some quick testing on my current platform
-    // still manages to parse the numbers such as "3.14" even if the decimal for the
-    // locale is ",".
+	// WinCE doesn't have setlocale. Some quick testing on my current platform
+	// still manages to parse the numbers such as "3.14" even if the decimal for the
+	// locale is ",".
 #if !defined(_WIN32_WCE) && !defined(ANDROID) && !defined(__psp2__)
 	// Set the locale to C so that we are guaranteed to parse the float value correctly
 	char *orig = setlocale(LC_NUMERIC, 0);
@@ -578,7 +665,7 @@ static string StringSubString(asUINT start, int count, const string &str)
 	// Check for out-of-bounds
 	string ret;
 	if( start < str.length() && count != 0 )
-		ret = str.substr(start, count);
+		ret = str.substr(start, (size_t)(count < 0 ? string::npos : count));
 
 	return ret;
 }
@@ -591,7 +678,7 @@ static string StringSubString(asUINT start, int count, const string &str)
 // makro, so this wrapper was introduced as work around.
 static bool StringEquals(const std::string& lhs, const std::string& rhs)
 {
-    return lhs == rhs;
+	return lhs == rhs;
 }
 
 void RegisterStdString_Native(asIScriptEngine *engine)
@@ -607,16 +694,7 @@ void RegisterStdString_Native(asIScriptEngine *engine)
 	r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
 #endif
 
-#if AS_USE_STRINGPOOL == 1
-	// Register the string factory
-	r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );
-
-	// Register the cleanup callback for the string pool
-	engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL);
-#else
-	// Register the string factory
-	r = engine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );
-#endif
+	r = engine->RegisterStringFactory("string", &stringFactory);
 
 	// Register the object operator overloads
 	r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT,  "void f()",                    asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
@@ -675,11 +753,20 @@ void RegisterStdString_Native(asIScriptEngine *engine)
 	// Utilities
 	r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("string", "int findFirstOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstOf), asCALL_CDECL_OBJLAST); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findFirstNotOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstNotOf), asCALL_CDECL_OBJLAST); assert(r >= 0);
 	r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("string", "int findLastOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastOf), asCALL_CDECL_OBJLAST); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findLastNotOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastNotOf), asCALL_CDECL_OBJLAST); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "void insert(uint pos, const string &in other)", asFUNCTION(StringInsert), asCALL_CDECL_OBJLAST); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "void erase(uint pos, int count = -1)", asFUNCTION(StringErase), asCALL_CDECL_OBJLAST); assert(r >= 0);
 
-	r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options, uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0);
-	r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options, uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0);
+
+	r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt), asCALL_CDECL); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0);
 	r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt), asCALL_CDECL); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("uint64 parseUInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseUInt), asCALL_CDECL); assert(r >= 0);
 	r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat), asCALL_CDECL); assert(r >= 0);
 
 #if AS_USE_STLNAMES == 1
@@ -694,112 +781,103 @@ void RegisterStdString_Native(asIScriptEngine *engine)
 #endif
 
 	// TODO: Implement the following
-	// findFirstOf
-	// findLastOf
-	// findFirstNotOf
-	// findLastNotOf
 	// findAndReplace - replaces a text found in the string
 	// replaceRange - replaces a range of bytes in the string
-	// trim/trimLeft/trimRight
 	// multiply/times/opMul/opMul_r - takes the string and multiplies it n times, e.g. "-".multiply(5) returns "-----"
 }
 
-#if AS_USE_STRINGPOOL == 1
-static void StringFactoryGeneric(asIScriptGeneric *gen)
-{
-  asUINT length = gen->GetArgDWord(0);
-  const char *s = (const char*)gen->GetArgAddress(1);
-
-  // Return a reference to a string
-  gen->SetReturnAddress(const_cast<string*>(&StringFactory(length, s)));
-}
-#else
-static void StringFactoryGeneric(asIScriptGeneric *gen)
-{
-  asUINT length = gen->GetArgDWord(0);
-  const char *s = (const char*)gen->GetArgAddress(1);
-
-  // Return a string value
-  new (gen->GetAddressOfReturnLocation()) string(StringFactory(length, s));
-}
-#endif
-
 static void ConstructStringGeneric(asIScriptGeneric * gen)
 {
-  new (gen->GetObject()) string();
+	new (gen->GetObject()) string();
 }
 
 static void CopyConstructStringGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetArgObject(0));
-  new (gen->GetObject()) string(*a);
+	string * a = static_cast<string *>(gen->GetArgObject(0));
+	new (gen->GetObject()) string(*a);
 }
 
 static void DestructStringGeneric(asIScriptGeneric * gen)
 {
-  string * ptr = static_cast<string *>(gen->GetObject());
-  ptr->~string();
+	string * ptr = static_cast<string *>(gen->GetObject());
+	ptr->~string();
 }
 
 static void AssignStringGeneric(asIScriptGeneric *gen)
 {
-  string * a = static_cast<string *>(gen->GetArgObject(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  *self = *a;
-  gen->SetReturnAddress(self);
+	string * a = static_cast<string *>(gen->GetArgObject(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	*self = *a;
+	gen->SetReturnAddress(self);
 }
 
 static void AddAssignStringGeneric(asIScriptGeneric *gen)
 {
-  string * a = static_cast<string *>(gen->GetArgObject(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  *self += *a;
-  gen->SetReturnAddress(self);
+	string * a = static_cast<string *>(gen->GetArgObject(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	*self += *a;
+	gen->SetReturnAddress(self);
 }
 
 static void StringEqualsGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  string * b = static_cast<string *>(gen->GetArgAddress(0));
-  *(bool*)gen->GetAddressOfReturnLocation() = (*a == *b);
+	string * a = static_cast<string *>(gen->GetObject());
+	string * b = static_cast<string *>(gen->GetArgAddress(0));
+	*(bool*)gen->GetAddressOfReturnLocation() = (*a == *b);
 }
 
 static void StringCmpGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  string * b = static_cast<string *>(gen->GetArgAddress(0));
+	string * a = static_cast<string *>(gen->GetObject());
+	string * b = static_cast<string *>(gen->GetArgAddress(0));
 
-  int cmp = 0;
-  if( *a < *b ) cmp = -1;
-  else if( *a > *b ) cmp = 1;
+	int cmp = 0;
+	if( *a < *b ) cmp = -1;
+	else if( *a > *b ) cmp = 1;
 
-  *(int*)gen->GetAddressOfReturnLocation() = cmp;
+	*(int*)gen->GetAddressOfReturnLocation() = cmp;
 }
 
 static void StringAddGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  string * b = static_cast<string *>(gen->GetArgAddress(0));
-  string ret_val = *a + *b;
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	string * b = static_cast<string *>(gen->GetArgAddress(0));
+	string ret_val = *a + *b;
+	gen->SetReturnObject(&ret_val);
 }
 
 static void StringLengthGeneric(asIScriptGeneric * gen)
 {
-  string * self = static_cast<string *>(gen->GetObject());
-  *static_cast<asUINT *>(gen->GetAddressOfReturnLocation()) = (asUINT)self->length();
+	string * self = static_cast<string *>(gen->GetObject());
+	*static_cast<asUINT *>(gen->GetAddressOfReturnLocation()) = (asUINT)self->length();
 }
 
 static void StringIsEmptyGeneric(asIScriptGeneric * gen)
 {
-  string * self = reinterpret_cast<string *>(gen->GetObject());
-  *reinterpret_cast<bool *>(gen->GetAddressOfReturnLocation()) = StringIsEmpty(*self);
+	string * self = reinterpret_cast<string *>(gen->GetObject());
+	*reinterpret_cast<bool *>(gen->GetAddressOfReturnLocation()) = StringIsEmpty(*self);
 }
 
 static void StringResizeGeneric(asIScriptGeneric * gen)
 {
-  string * self = static_cast<string *>(gen->GetObject());
-  self->resize(*static_cast<asUINT *>(gen->GetAddressOfArg(0)));
+	string * self = static_cast<string *>(gen->GetObject());
+	self->resize(*static_cast<asUINT *>(gen->GetAddressOfArg(0)));
+}
+
+static void StringInsert_Generic(asIScriptGeneric *gen)
+{
+	string * self = static_cast<string *>(gen->GetObject());
+	asUINT pos = gen->GetArgDWord(0);
+	string *other = reinterpret_cast<string*>(gen->GetArgAddress(1));
+	StringInsert(pos, *other, *self);
+}
+
+static void StringErase_Generic(asIScriptGeneric *gen)
+{
+	string * self = static_cast<string *>(gen->GetObject());
+	asUINT pos = gen->GetArgDWord(0);
+	int count = int(gen->GetArgDWord(1));
+	StringErase(pos, count, *self);
 }
 
 static void StringFindFirst_Generic(asIScriptGeneric * gen)
@@ -818,6 +896,38 @@ static void StringFindLast_Generic(asIScriptGeneric * gen)
 	*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) = StringFindLast(*find, start, *self);
 }
 
+static void StringFindFirstOf_Generic(asIScriptGeneric * gen)
+{
+	string *find = reinterpret_cast<string*>(gen->GetArgAddress(0));
+	asUINT start = gen->GetArgDWord(1);
+	string *self = reinterpret_cast<string *>(gen->GetObject());
+	*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) = StringFindFirstOf(*find, start, *self);
+}
+
+static void StringFindLastOf_Generic(asIScriptGeneric * gen)
+{
+	string *find = reinterpret_cast<string*>(gen->GetArgAddress(0));
+	asUINT start = gen->GetArgDWord(1);
+	string *self = reinterpret_cast<string *>(gen->GetObject());
+	*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) = StringFindLastOf(*find, start, *self);
+}
+
+static void StringFindFirstNotOf_Generic(asIScriptGeneric * gen)
+{
+	string *find = reinterpret_cast<string*>(gen->GetArgAddress(0));
+	asUINT start = gen->GetArgDWord(1);
+	string *self = reinterpret_cast<string *>(gen->GetObject());
+	*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) = StringFindFirstNotOf(*find, start, *self);
+}
+
+static void StringFindLastNotOf_Generic(asIScriptGeneric * gen)
+{
+	string *find = reinterpret_cast<string*>(gen->GetArgAddress(0));
+	asUINT start = gen->GetArgDWord(1);
+	string *self = reinterpret_cast<string *>(gen->GetObject());
+	*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) = StringFindLastNotOf(*find, start, *self);
+}
+
 static void formatInt_Generic(asIScriptGeneric * gen)
 {
 	asINT64 val = gen->GetArgQWord(0);
@@ -826,6 +936,14 @@ static void formatInt_Generic(asIScriptGeneric * gen)
 	new(gen->GetAddressOfReturnLocation()) string(formatInt(val, *options, width));
 }
 
+static void formatUInt_Generic(asIScriptGeneric * gen)
+{
+	asQWORD val = gen->GetArgQWord(0);
+	string *options = reinterpret_cast<string*>(gen->GetArgAddress(1));
+	asUINT width = gen->GetArgDWord(2);
+	new(gen->GetAddressOfReturnLocation()) string(formatUInt(val, *options, width));
+}
+
 static void formatFloat_Generic(asIScriptGeneric *gen)
 {
 	double val = gen->GetArgDouble(0);
@@ -843,6 +961,14 @@ static void parseInt_Generic(asIScriptGeneric *gen)
 	gen->SetReturnQWord(parseInt(*str,base,byteCount));
 }
 
+static void parseUInt_Generic(asIScriptGeneric *gen)
+{
+	string *str = reinterpret_cast<string*>(gen->GetArgAddress(0));
+	asUINT base = gen->GetArgDWord(1);
+	asUINT *byteCount = reinterpret_cast<asUINT*>(gen->GetArgAddress(2));
+	gen->SetReturnQWord(parseUInt(*str, base, byteCount));
+}
+
 static void parseFloat_Generic(asIScriptGeneric *gen)
 {
 	string *str = reinterpret_cast<string*>(gen->GetArgAddress(0));
@@ -852,21 +978,21 @@ static void parseFloat_Generic(asIScriptGeneric *gen)
 
 static void StringCharAtGeneric(asIScriptGeneric * gen)
 {
-  unsigned int index = gen->GetArgDWord(0);
-  string * self = static_cast<string *>(gen->GetObject());
+	unsigned int index = gen->GetArgDWord(0);
+	string * self = static_cast<string *>(gen->GetObject());
 
-  if (index >= self->size())
-  {
-    // Set a script exception
-    asIScriptContext *ctx = asGetActiveContext();
-    ctx->SetException("Out of range");
+	if (index >= self->size())
+	{
+		// Set a script exception
+		asIScriptContext *ctx = asGetActiveContext();
+		ctx->SetException("Out of range");
 
-    gen->SetReturnAddress(0);
-  }
-  else
-  {
-    gen->SetReturnAddress(&(self->operator [](index)));
-  }
+		gen->SetReturnAddress(0);
+	}
+	else
+	{
+		gen->SetReturnAddress(&(self->operator [](index)));
+	}
 }
 
 static void AssignInt2StringGeneric(asIScriptGeneric *gen)
@@ -921,163 +1047,163 @@ static void AssignBool2StringGeneric(asIScriptGeneric *gen)
 
 static void AddAssignDouble2StringGeneric(asIScriptGeneric * gen)
 {
-  double * a = static_cast<double *>(gen->GetAddressOfArg(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a;
-  *self += sstr.str();
-  gen->SetReturnAddress(self);
+	double * a = static_cast<double *>(gen->GetAddressOfArg(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a;
+	*self += sstr.str();
+	gen->SetReturnAddress(self);
 }
 
 static void AddAssignFloat2StringGeneric(asIScriptGeneric * gen)
 {
-  float * a = static_cast<float *>(gen->GetAddressOfArg(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a;
-  *self += sstr.str();
-  gen->SetReturnAddress(self);
+	float * a = static_cast<float *>(gen->GetAddressOfArg(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a;
+	*self += sstr.str();
+	gen->SetReturnAddress(self);
 }
 
 static void AddAssignInt2StringGeneric(asIScriptGeneric * gen)
 {
-  asINT64 * a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a;
-  *self += sstr.str();
-  gen->SetReturnAddress(self);
+	asINT64 * a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a;
+	*self += sstr.str();
+	gen->SetReturnAddress(self);
 }
 
 static void AddAssignUInt2StringGeneric(asIScriptGeneric * gen)
 {
-  asQWORD * a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a;
-  *self += sstr.str();
-  gen->SetReturnAddress(self);
+	asQWORD * a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a;
+	*self += sstr.str();
+	gen->SetReturnAddress(self);
 }
 
 static void AddAssignBool2StringGeneric(asIScriptGeneric * gen)
 {
-  bool * a = static_cast<bool *>(gen->GetAddressOfArg(0));
-  string * self = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << (*a ? "true" : "false");
-  *self += sstr.str();
-  gen->SetReturnAddress(self);
+	bool * a = static_cast<bool *>(gen->GetAddressOfArg(0));
+	string * self = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << (*a ? "true" : "false");
+	*self += sstr.str();
+	gen->SetReturnAddress(self);
 }
 
 static void AddString2DoubleGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  double * b = static_cast<double *>(gen->GetAddressOfArg(0));
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	double * b = static_cast<double *>(gen->GetAddressOfArg(0));
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddString2FloatGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  float * b = static_cast<float *>(gen->GetAddressOfArg(0));
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	float * b = static_cast<float *>(gen->GetAddressOfArg(0));
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddString2IntGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  asINT64 * b = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	asINT64 * b = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddString2UIntGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  asQWORD * b = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	asQWORD * b = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddString2BoolGeneric(asIScriptGeneric * gen)
 {
-  string * a = static_cast<string *>(gen->GetObject());
-  bool * b = static_cast<bool *>(gen->GetAddressOfArg(0));
-  std::stringstream sstr;
-  sstr << *a << (*b ? "true" : "false");
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	string * a = static_cast<string *>(gen->GetObject());
+	bool * b = static_cast<bool *>(gen->GetAddressOfArg(0));
+	std::stringstream sstr;
+	sstr << *a << (*b ? "true" : "false");
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddDouble2StringGeneric(asIScriptGeneric * gen)
 {
-  double* a = static_cast<double *>(gen->GetAddressOfArg(0));
-  string * b = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	double* a = static_cast<double *>(gen->GetAddressOfArg(0));
+	string * b = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddFloat2StringGeneric(asIScriptGeneric * gen)
 {
-  float* a = static_cast<float *>(gen->GetAddressOfArg(0));
-  string * b = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	float* a = static_cast<float *>(gen->GetAddressOfArg(0));
+	string * b = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddInt2StringGeneric(asIScriptGeneric * gen)
 {
-  asINT64* a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
-  string * b = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	asINT64* a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
+	string * b = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddUInt2StringGeneric(asIScriptGeneric * gen)
 {
-  asQWORD* a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
-  string * b = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << *a << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	asQWORD* a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
+	string * b = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << *a << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void AddBool2StringGeneric(asIScriptGeneric * gen)
 {
-  bool* a = static_cast<bool *>(gen->GetAddressOfArg(0));
-  string * b = static_cast<string *>(gen->GetObject());
-  std::stringstream sstr;
-  sstr << (*a ? "true" : "false") << *b;
-  std::string ret_val = sstr.str();
-  gen->SetReturnObject(&ret_val);
+	bool* a = static_cast<bool *>(gen->GetAddressOfArg(0));
+	string * b = static_cast<string *>(gen->GetObject());
+	std::stringstream sstr;
+	sstr << (*a ? "true" : "false") << *b;
+	std::string ret_val = sstr.str();
+	gen->SetReturnObject(&ret_val);
 }
 
 static void StringSubString_Generic(asIScriptGeneric *gen)
 {
-    // Get the arguments
-    string *str   = (string*)gen->GetObject();
-    asUINT  start = *(int*)gen->GetAddressOfArg(0);
-    int     count = *(int*)gen->GetAddressOfArg(1);
+	// Get the arguments
+	string *str   = (string*)gen->GetObject();
+	asUINT  start = *(int*)gen->GetAddressOfArg(0);
+	int     count = *(int*)gen->GetAddressOfArg(1);
 
 	// Return the substring
-    new(gen->GetAddressOfReturnLocation()) string(StringSubString(start, count, *str));
+	new(gen->GetAddressOfReturnLocation()) string(StringSubString(start, count, *str));
 }
 
 void RegisterStdString_Generic(asIScriptEngine *engine)
@@ -1088,16 +1214,7 @@ void RegisterStdString_Generic(asIScriptEngine *engine)
 	// Register the string type
 	r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
 
-#if AS_USE_STRINGPOOL == 1
-	// Register the string factory
-	r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 );
-
-	// Register the cleanup callback for the string pool
-	engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL);
-#else
-	// Register the string factory
-	r = engine->RegisterStringFactory("string", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 );
-#endif
+	r = engine->RegisterStringFactory("string", &stringFactory);
 
 	// Register the object operator overloads
 	r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT,  "void f()",                    asFUNCTION(ConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 );
@@ -1147,13 +1264,22 @@ void RegisterStdString_Generic(asIScriptEngine *engine)
 	r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddString2BoolGeneric), asCALL_GENERIC); assert( r >= 0 );
 	r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 );
 
-	r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert( r >= 0 );
-	r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert( r >= 0 );
+	r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findFirstOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstOf_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findFirstNotOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstNotOf_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findLastOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastOf_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "int findLastNotOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastNotOf_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "void insert(uint pos, const string &in other)", asFUNCTION(StringInsert_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterObjectMethod("string", "void erase(uint pos, int count = -1)", asFUNCTION(StringErase_Generic), asCALL_GENERIC); assert(r >= 0);
+
 
-	r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options, uint width = 0)", asFUNCTION(formatInt_Generic), asCALL_GENERIC); assert(r >= 0);
-	r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options, uint width = 0, uint precision = 0)", asFUNCTION(formatFloat_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat_Generic), asCALL_GENERIC); assert(r >= 0);
 	r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt_Generic), asCALL_GENERIC); assert(r >= 0);
+	r = engine->RegisterGlobalFunction("uint64 parseUInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseUInt_Generic), asCALL_GENERIC); assert(r >= 0);
 	r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat_Generic), asCALL_GENERIC); assert(r >= 0);
 }
 
diff --git a/src/scriptengine/scriptstdstring.hpp b/src/scriptengine/scriptstdstring.hpp
index d7e3a49c6..9d8ac53cf 100644
--- a/src/scriptengine/scriptstdstring.hpp
+++ b/src/scriptengine/scriptstdstring.hpp
@@ -11,29 +11,17 @@
 #ifndef SCRIPTSTDSTRING_H
 #define SCRIPTSTDSTRING_H
 
-// String must be included before angelscript.h to avoid some errors during
-// compilation with GetObject function
-#include <string>
-
 #ifndef ANGELSCRIPT_H 
 // Avoid having to inform include path if header is already include before
 #include <angelscript.h>
 #endif
 
+#include <string>
+
 //---------------------------
 // Compilation settings
 //
 
-// The use of the string pool can improve performance quite drastically
-// for scripts that work with a lot of literal string constants. 
-//
-//  1 = on
-//  0 = off
-
-#ifndef AS_USE_STRINGPOOL
-#define AS_USE_STRINGPOOL 1
-#endif
-
 // Sometimes it may be desired to use the same method names as used by C++ STL.
 // This may for example reduce time when converting code from script to C++ or
 // back.
diff --git a/src/scriptengine/scriptstdstring_utils.cpp b/src/scriptengine/scriptstdstring_utils.cpp
index d46fea751..3abd02896 100644
--- a/src/scriptengine/scriptstdstring_utils.cpp
+++ b/src/scriptengine/scriptstdstring_utils.cpp
@@ -28,7 +28,7 @@ static CScriptArray *StringSplit(const string &delim, const string &str)
 
 	// TODO: This should only be done once
 	// TODO: This assumes that CScriptArray was already registered
-	asIObjectType *arrayType = engine->GetObjectTypeByDecl("array<string>");
+	asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
 
 	// Create the array object
 	CScriptArray *array = CScriptArray::Create(arrayType);