Skip to content

Commit ad1709e

Browse files
committed
v1.3
1 parent feff68d commit ad1709e

File tree

5 files changed

+162
-57
lines changed

5 files changed

+162
-57
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## Version 1.3
4+
5+
Version: 1.3
6+
Author: monkey0506
7+
Date: 21 August 2009
8+
Description: Fixed bug with `String.Format` and large `Stack`s (`String.Format` has a limit on the
9+
size of the `String` it can return; replaced where applicable with `String.Append` instead). Also
10+
added further support to prevent issues with `Stack.Copy`. Previously if you pushed the same stack
11+
copy onto a single stack multiple times there would be problems with the internal data structure.
12+
This should resolve that.
13+
314
## Version 1.2a
415

516
Version: 1.2a

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ AGS v3.1.2+
2929

3030
Defines the current version of the module, formatted as a `float`.
3131

32+
#### Stack_VERSION_130
33+
34+
Defines version 1.3 of the module.
35+
3236
#### Stack_VERSION_120
3337

3438
Defines version 1.2 of the module.

Stack.asc

Lines changed: 129 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ String StackDataCopyFormat;
66

77
StackDataType GetType(this StackData*) {
88
if (this.Length < (StackDataFormat.Length - 1)) return eStackDataInvalid;
9-
StackData type = this.Substring(0, StackDataFormat.Length - 1);
9+
String type = this.Substring(0, StackDataFormat.Length - 1);
1010
int i = type.IndexOf(":");
1111
if (i == -1) return eStackDataInvalid;
1212
char c = type.Chars[i + 1];
@@ -70,48 +70,48 @@ GUIControl* GetAsGUIControl(this StackData*) {
7070
}
7171

7272
static StackData Stack::IntToData(int theInt) {
73-
StackData type = StackData.Format(StackDataFormat, eStackDataInt);
74-
return StackData.Format("%s%d", type, theInt);
73+
String type = String.Format(StackDataFormat, eStackDataInt);
74+
return String.Format("%s%d", type, theInt);
7575
}
7676

7777
static StackData Stack::FloatToData(float theFloat) {
78-
StackData type = StackData.Format(StackDataFormat, eStackDataFloat);
79-
return StackData.Format("%s%f", type, theFloat);
78+
String type = String.Format(StackDataFormat, eStackDataFloat);
79+
return String.Format("%s%f", type, theFloat);
8080
}
8181

8282
static StackData Stack::StringToData(String theString) {
83-
StackData type = StackData.Format(StackDataFormat, eStackDataString);
83+
String type = String.Format(StackDataFormat, eStackDataString);
8484
return type.Append(theString);
8585
}
8686

8787
static StackData Stack::CharacterToData(Character *theCharacter) {
8888
if (theCharacter == null) return null;
89-
StackData type = StackData.Format(StackDataFormat, eStackDataCharacter);
90-
return StackData.Format("%s%d", type, theCharacter.ID);
89+
String type = String.Format(StackDataFormat, eStackDataCharacter);
90+
return String.Format("%s%d", type, theCharacter.ID);
9191
}
9292

9393
static StackData Stack::InventoryItemToData(InventoryItem *theItem) {
9494
if (theItem == null) return null;
95-
StackData type = StackData.Format(StackDataFormat, eStackDataInventoryItem);
96-
return StackData.Format("%s%d", type, theItem.ID);
95+
String type = String.Format(StackDataFormat, eStackDataInventoryItem);
96+
return String.Format("%s%d", type, theItem.ID);
9797
}
9898

9999
static StackData Stack::GUIToData(GUI *theGUI) {
100100
if (theGUI == null) return null;
101-
StackData type = StackData.Format(StackDataFormat, eStackDataGUI);
102-
return StackData.Format("%s%d", type, theGUI.ID);
101+
String type = String.Format(StackDataFormat, eStackDataGUI);
102+
return String.Format("%s%d", type, theGUI.ID);
103103
}
104104

105105
static StackData Stack::GUIControlToData(GUIControl *theControl) {
106106
if (theControl == null) return null;
107-
StackData type = StackData.Format(StackDataFormat, eStackDataGUIControl);
108-
return StackData.Format("%s%d", type, ((theControl.OwningGUI.ID * AGS_MAX_CONTROLS_PER_GUI) + theControl.ID));
107+
String type = String.Format(StackDataFormat, eStackDataGUIControl);
108+
return String.Format("%s%d", type, ((theControl.OwningGUI.ID * AGS_MAX_CONTROLS_PER_GUI) + theControl.ID));
109109
}
110110

111111
StackData MergeArray(this Stack*, StackData array[]) {
112112
if (array == null) return null;
113-
StackData glue = StackDataDelimiter;
114-
StackData buffer = "";
113+
String glue = StackDataDelimiter;
114+
String buffer = "";
115115
int i = 0;
116116
int size = this.ItemCount;
117117
while (i < size) {
@@ -124,16 +124,16 @@ StackData MergeArray(this Stack*, StackData array[]) {
124124

125125
StackData[] GetItemsArray(this Stack*) {
126126
if ((this.Data == null) || (!this.ItemCount)) return null;
127-
StackData items[] = new StackData[this.ItemCount];
128-
StackData buffer = this.Data;
127+
String items[] = new String[this.ItemCount];
128+
String buffer = this.Data;
129129
String format = StackDataFormat.Substring(0, StackDataFormat.IndexOf(":") + 1);
130130
int i = buffer.IndexOf(format);
131131
int j = 0;
132132
while ((i != -1) && (j < this.ItemCount)) {
133133
StackDataType type = buffer.Chars[format.Length];
134134
if (type == eStackDataStack) {
135-
StackData temp = buffer.Substring(StackDataFormat.Length - 1, buffer.Length);
136-
StackData stamp = temp.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
135+
String temp = buffer.Substring(StackDataFormat.Length - 1, buffer.Length);
136+
String stamp = temp.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
137137
temp = temp.Substring(stamp.Length, temp.Length);
138138
i = temp.IndexOf(stamp);
139139
if (i != -1) items[j] = buffer.Truncate(i + (StackDataFormat.Length - 1) + (stamp.Length * 2));
@@ -160,15 +160,108 @@ StackData[] GetItemsArray(this Stack*) {
160160
return items;
161161
}
162162

163+
#ifndef StringPlus_VERSION
164+
String[] SplitByString(this String*, String otherString) {
165+
String s[];
166+
int i = this.IndexOf(otherString);
167+
if ((String.IsNullOrEmpty(otherString)) || (i == -1)) {
168+
s = new String[2];
169+
s[0] = "1";
170+
s[1] = this;
171+
return s;
172+
}
173+
s = new String[this.Length + 1];
174+
String buffer = this;
175+
int lineCount = 0;
176+
while (i != -1) {
177+
lineCount++;
178+
s[lineCount] = buffer.Substring(0, i);
179+
i += otherString.Length;
180+
if (i < buffer.Length) {
181+
buffer = buffer.Substring(i, buffer.Length);
182+
i = buffer.IndexOf(otherString);
183+
}
184+
else i = -1;
185+
}
186+
lineCount++;
187+
s[lineCount] = buffer;
188+
String t[] = new String[lineCount + 1];
189+
i = 1;
190+
while (i <= lineCount) {
191+
t[i] = s[i];
192+
i++;
193+
}
194+
t[0] = String.Format("%d", lineCount);
195+
return t;
196+
}
197+
198+
String StringMergeArray(String array[], String glue) {
199+
if ((array == null) || (String.IsNullOrEmpty(array[0])) || (array[0].AsInt <= 0)) return null;
200+
if (glue == null) glue = "";
201+
String buffer = "";
202+
int i = 1;
203+
int size = array[0].AsInt;
204+
while (i <= size) {
205+
buffer = buffer.Append(array[i]);
206+
if (i < size) buffer = buffer.Append(glue);
207+
i++;
208+
}
209+
return buffer;
210+
}
211+
#endif
212+
213+
StackData BuildKey(this Stack*) { // returns a 128-bit (16-byte) key for Stack::Copy
214+
String key = "";
215+
int i = 0;
216+
while (i < 16) {
217+
char c = 0;
218+
int j = 7;
219+
while (j >= 0) { // build-a-byte
220+
DateTime *now = DateTime.Now;
221+
bool bit = (Random(now.RawTime) % 2); // returns either 1 or 0
222+
c += (bit << j); // then we shift that bit into place
223+
j--;
224+
}
225+
if (c) {
226+
key = key.AppendChar(c);
227+
i++;
228+
}
229+
}
230+
return key;
231+
}
232+
233+
StackData MaskStacksForCopy(this Stack*) {
234+
// regenerates any existing Stack keys (see BuildKey) when pushing a Stack object (copy) onto this stack
235+
// prevents issues with the data structure
236+
if (String.IsNullOrEmpty(this.Data)) return this.Data;
237+
String s[] = this.Data.SplitByString(StackDataCopyFormat.Substring(0, 18)); // split the data by the stacks within it
238+
if (s[0].AsInt == 1) return this.Data;
239+
int size = s[0].AsInt;
240+
// structure of S will be:
241+
// 1: **STACKDATA:k** - the data type, a stack
242+
// 2: XXXXXXXXXXXXXXXX**DATA - the 128-bit (16-byte) key originally assigned here followed by the stack's data
243+
// 3: XXXXXXXXXXXXXXXX** - the same key
244+
// the rest of StackDataCopyFormat is removed by SplitByString
245+
int i = 2; // start at the first available key
246+
while (i < size) {
247+
String key = this.BuildKey(); // grab a new key
248+
s[i] = key.Append(s[i].Substring(16, s[i].Length)); // replace both instances
249+
s[i + 1] = key.Append(s[i + 1].Substring(16, s[i + 1].Length));
250+
i += 3; // increasing by 3 sets I to the next "2" index in the structure
251+
}
252+
return StringMergeArray(s, StackDataCopyFormat.Substring(0, 18));
253+
}
254+
163255
bool Stack::Push(StackData data, int index) {
164256
if ((index == SCR_NO_VALUE) || (index > this.ItemCount)) index = this.ItemCount;
165257
if ((index < 0) || (data == null)) return false;
166-
if (StackData.IsNullOrEmpty(this.Data)) {
258+
if (String.IsNullOrEmpty(this.Data)) {
167259
this.Data = data;
168260
this.ItemCount++;
169261
return true;
170262
}
171-
StackData items[] = this.GetItemsArray();
263+
if (data.GetType() == eStackDataStack) this.Data = this.MaskStacksForCopy(); // prevent issues if pushing the same stack multiple times
264+
String items[] = this.GetItemsArray();
172265
int size = this.ItemCount;
173266
if (index < size) items[index] = data;
174267
this.Data = this.MergeArray(items);
@@ -186,18 +279,18 @@ StackData Stack::Pop(bool remove, int index) {
186279
else if (this.PopType == eStackPopRandom) index = Random(this.ItemCount - 1);
187280
}
188281
if ((index < 0) || (index >= this.ItemCount) || (!this.ItemCount) ||
189-
(StackData.IsNullOrEmpty(this.Data))) return null;
190-
StackData items[] = this.GetItemsArray();
282+
(String.IsNullOrEmpty(this.Data))) return null;
283+
String items[] = this.GetItemsArray();
191284
int size = this.ItemCount;
192-
StackData data = items[index];
285+
String data = items[index];
193286
if (remove) {
194287
this.ItemCount--;
195288
if ((!this.ItemCount) || (size == 1)) {
196289
this.Data = null;
197290
items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
198291
return data;
199292
}
200-
StackData buffer[] = new StackData[this.ItemCount];
293+
String buffer[] = new String[this.ItemCount];
201294
int i = 0;
202295
while (i < this.ItemCount) {
203296
if (i < index) buffer[i] = items[i];
@@ -220,42 +313,23 @@ bool Stack::IsEmpty() {
220313
return (!this.ItemCount);
221314
}
222315

223-
StackData BuildKey(this Stack*) { // returns a 128-bit (16-byte) key for Stack::Copy
224-
StackData key = "";
225-
int i = 0;
226-
while (i < 16) {
227-
char c = 0;
228-
int j = 7;
229-
while (j >= 0) { // build-a-byte
230-
DateTime *now = DateTime.Now;
231-
bool bit = (Random(now.RawTime) % 2); // returns either 1 or 0
232-
c += (bit << j); // then we shift that bit into place
233-
j--;
234-
}
235-
if (c) {
236-
key = key.AppendChar(c);
237-
i++;
238-
}
239-
}
240-
return key;
241-
}
242-
243316
StackData Stack::Copy() {
244-
StackData type = StackData.Format(StackDataFormat, eStackDataStack);
245-
StackData key = this.BuildKey();
246-
StackData stamp = StackData.Format(StackDataCopyFormat, key);
247-
StackData data = this.Data;
317+
String type = String.Format(StackDataFormat, eStackDataStack);
318+
String key = this.BuildKey();
319+
String stamp = String.Format(StackDataCopyFormat, key);
320+
String data = this.Data;
248321
if (data == null) data = "";
249-
return StackData.Format("%s%s%d,%d,%s%s", type, stamp, this.ItemCount, this.PopType, data, stamp);
322+
String s = type.Append(stamp.Append(String.Format("%d,%d,", this.ItemCount, this.PopType)));
323+
return s.Append(data.Append(stamp));
250324
}
251325

252326
bool Stack::LoadFromStack(StackData otherStack) {
253327
if ((otherStack == null) || (otherStack.GetType() != eStackDataStack)) return false;
254-
StackData data = otherStack.Substring(StackDataFormat.Length - 1, otherStack.Length);
255-
StackData stamp = data.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
328+
String data = otherStack.Substring(StackDataFormat.Length - 1, otherStack.Length);
329+
String stamp = data.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
256330
data = data.Substring(stamp.Length, data.Length);
257331
data = data.Truncate(data.IndexOf(stamp));
258-
StackData buffer = data.Substring(0, data.IndexOf(","));
332+
String buffer = data.Substring(0, data.IndexOf(","));
259333
this.ItemCount = buffer.AsInt;
260334
data = data.Substring(buffer.Length + 1, data.Length);
261335
buffer = data.Substring(0, data.IndexOf(","));
@@ -272,7 +346,7 @@ bool WriteStack(this File*, StackData stackCopy) {
272346

273347
StackData ReadStackBack(this File*) {
274348
if ((this.Error) || (this.EOF)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
275-
StackData data = this.ReadStringBack();
349+
String data = this.ReadStringBack();
276350
if ((data == null) || (data.GetType() != eStackDataStack) || (this.Error)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
277351
return data;
278352
}

Stack.ash

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ AGS v3.1.2+
3030
3131
Defines the current version of the module, formatted as a `float`.
3232
33+
#### Stack_VERSION_130
34+
35+
Defines version 1.3 of the module.
36+
3337
#### Stack_VERSION_120
3438
3539
Defines version 1.2 of the module.
@@ -358,6 +362,17 @@ CONNECTION WITH THE MODULE OR THE USE OR OTHER DEALINGS IN THE MODULE.
358362
359363
# Changelog
360364
365+
## Version 1.3
366+
367+
Version: 1.3
368+
Author: monkey0506
369+
Date: 21 August 2009
370+
Description: Fixed bug with `String.Format` and large `Stack`s (`String.Format` has a limit on the
371+
size of the `String` it can return; replaced where applicable with `String.Append` instead). Also
372+
added further support to prevent issues with `Stack.Copy`. Previously if you pushed the same stack
373+
copy onto a single stack multiple times there would be problems with the internal data structure.
374+
This should resolve that.
375+
361376
## Version 1.2a
362377
363378
Version: 1.2a
@@ -389,7 +404,8 @@ Description: First public release.
389404

390405
#ifdef AGS_SUPPORTS_IFVER
391406
#ifver 3.1.2
392-
#define Stack_VERSION 1.2
407+
#define Stack_VERSION 1.3
408+
#define Stack_VERSION_130
393409
#define Stack_VERSION_120
394410
#define Stack_VERSION_100
395411
#endif

Stack.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
<Name>Stack</Name>
44
<Description>The Stack module introduces a vectorized stack type into which you can place any type of data. Great if you need to store data of various different types, or all of one type; this module can handle all of your data storage needs!</Description>
55
<Author>monkey0506</Author>
6-
<Version>v1.2a</Version>
6+
<Version>v1.3</Version>
77
<Key>918333590</Key>
88
</AGSModule>

0 commit comments

Comments
 (0)