1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include <assert.h>
#include "scriptstdstring.h"
#include "../scriptarray/scriptarray.h"
#include <stdio.h>
#include <string.h>
using namespace std;
BEGIN_AS_NAMESPACE
// This function takes an input string and splits it into parts by looking
// for a specified delimiter. Example:
//
// string str = "A|B||D";
// array<string>@ array = str.split("|");
//
// The resulting array has the following elements:
//
// {"A", "B", "", "D"}
//
// AngelScript signature:
// array<string>@ string::split(const string &in delim) const
static CScriptArray *StringSplit(const string &delim, const string &str) {
// Obtain a pointer to the engine
asIScriptContext *ctx = asGetActiveContext();
asIScriptEngine *engine = ctx->GetEngine();
// TODO: This should only be done once
// TODO: This assumes that CScriptArray was already registered
asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array<string>");
// Create the array object
CScriptArray *array = CScriptArray::Create(arrayType);
// Find the existence of the delimiter in the input string
int pos = 0, prev = 0, count = 0;
while ((pos = (int)str.find(delim, prev)) != (int)string::npos) {
// Add the part to the array
array->Resize(array->GetSize() + 1);
((string *)array->At(count))->assign(&str[prev], pos - prev);
// Find the next part
count++;
prev = pos + (int)delim.length();
}
// Add the remaining part
array->Resize(array->GetSize() + 1);
((string *)array->At(count))->assign(&str[prev]);
return array;
}
static void StringSplit_Generic(asIScriptGeneric *gen) {
// Get the arguments
string *str = (string *)gen->GetObject();
string *delim = *(string **)gen->GetAddressOfArg(0);
// Return the array by handle
*(CScriptArray **)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str);
}
// This function takes as input an array of string handles as well as a
// delimiter and concatenates the array elements into one delimited string.
// Example:
//
// array<string> array = {"A", "B", "", "D"};
// string str = join(array, "|");
//
// The resulting string is:
//
// "A|B||D"
//
// AngelScript signature:
// string join(const array<string> &in array, const string &in delim)
static string StringJoin(const CScriptArray &array, const string &delim) {
// Create the new string
string str = "";
if (array.GetSize()) {
int n;
for (n = 0; n < (int)array.GetSize() - 1; n++) {
str += *(string *)array.At(n);
str += delim;
}
// Add the last part
str += *(string *)array.At(n);
}
return str;
}
static void StringJoin_Generic(asIScriptGeneric *gen) {
// Get the arguments
CScriptArray *array = *(CScriptArray **)gen->GetAddressOfArg(0);
string *delim = *(string **)gen->GetAddressOfArg(1);
// Return the string
new (gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim));
}
// This is where the utility functions are registered.
// The string type must have been registered first.
void RegisterStdStringUtils(asIScriptEngine *engine) {
int r;
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) {
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC);
assert(r >= 0);
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC);
assert(r >= 0);
} else {
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST);
assert(r >= 0);
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL);
assert(r >= 0);
}
}
END_AS_NAMESPACE
|