Skip to content

Commit

Permalink
v1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
monkey0506 committed Jun 30, 2017
1 parent feff68d commit ad1709e
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 57 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Version 1.3

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

## Version 1.2a

Version: 1.2a
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ AGS v3.1.2+

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

#### Stack_VERSION_130

Defines version 1.3 of the module.

#### Stack_VERSION_120

Defines version 1.2 of the module.
Expand Down
184 changes: 129 additions & 55 deletions Stack.asc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ String StackDataCopyFormat;

StackDataType GetType(this StackData*) {
if (this.Length < (StackDataFormat.Length - 1)) return eStackDataInvalid;
StackData type = this.Substring(0, StackDataFormat.Length - 1);
String type = this.Substring(0, StackDataFormat.Length - 1);
int i = type.IndexOf(":");
if (i == -1) return eStackDataInvalid;
char c = type.Chars[i + 1];
Expand Down Expand Up @@ -70,48 +70,48 @@ GUIControl* GetAsGUIControl(this StackData*) {
}

static StackData Stack::IntToData(int theInt) {
StackData type = StackData.Format(StackDataFormat, eStackDataInt);
return StackData.Format("%s%d", type, theInt);
String type = String.Format(StackDataFormat, eStackDataInt);
return String.Format("%s%d", type, theInt);
}

static StackData Stack::FloatToData(float theFloat) {
StackData type = StackData.Format(StackDataFormat, eStackDataFloat);
return StackData.Format("%s%f", type, theFloat);
String type = String.Format(StackDataFormat, eStackDataFloat);
return String.Format("%s%f", type, theFloat);
}

static StackData Stack::StringToData(String theString) {
StackData type = StackData.Format(StackDataFormat, eStackDataString);
String type = String.Format(StackDataFormat, eStackDataString);
return type.Append(theString);
}

static StackData Stack::CharacterToData(Character *theCharacter) {
if (theCharacter == null) return null;
StackData type = StackData.Format(StackDataFormat, eStackDataCharacter);
return StackData.Format("%s%d", type, theCharacter.ID);
String type = String.Format(StackDataFormat, eStackDataCharacter);
return String.Format("%s%d", type, theCharacter.ID);
}

static StackData Stack::InventoryItemToData(InventoryItem *theItem) {
if (theItem == null) return null;
StackData type = StackData.Format(StackDataFormat, eStackDataInventoryItem);
return StackData.Format("%s%d", type, theItem.ID);
String type = String.Format(StackDataFormat, eStackDataInventoryItem);
return String.Format("%s%d", type, theItem.ID);
}

static StackData Stack::GUIToData(GUI *theGUI) {
if (theGUI == null) return null;
StackData type = StackData.Format(StackDataFormat, eStackDataGUI);
return StackData.Format("%s%d", type, theGUI.ID);
String type = String.Format(StackDataFormat, eStackDataGUI);
return String.Format("%s%d", type, theGUI.ID);
}

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

StackData MergeArray(this Stack*, StackData array[]) {
if (array == null) return null;
StackData glue = StackDataDelimiter;
StackData buffer = "";
String glue = StackDataDelimiter;
String buffer = "";
int i = 0;
int size = this.ItemCount;
while (i < size) {
Expand All @@ -124,16 +124,16 @@ StackData MergeArray(this Stack*, StackData array[]) {

StackData[] GetItemsArray(this Stack*) {
if ((this.Data == null) || (!this.ItemCount)) return null;
StackData items[] = new StackData[this.ItemCount];
StackData buffer = this.Data;
String items[] = new String[this.ItemCount];
String buffer = this.Data;
String format = StackDataFormat.Substring(0, StackDataFormat.IndexOf(":") + 1);
int i = buffer.IndexOf(format);
int j = 0;
while ((i != -1) && (j < this.ItemCount)) {
StackDataType type = buffer.Chars[format.Length];
if (type == eStackDataStack) {
StackData temp = buffer.Substring(StackDataFormat.Length - 1, buffer.Length);
StackData stamp = temp.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
String temp = buffer.Substring(StackDataFormat.Length - 1, buffer.Length);
String stamp = temp.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
temp = temp.Substring(stamp.Length, temp.Length);
i = temp.IndexOf(stamp);
if (i != -1) items[j] = buffer.Truncate(i + (StackDataFormat.Length - 1) + (stamp.Length * 2));
Expand All @@ -160,15 +160,108 @@ StackData[] GetItemsArray(this Stack*) {
return items;
}

#ifndef StringPlus_VERSION
String[] SplitByString(this String*, String otherString) {
String s[];
int i = this.IndexOf(otherString);
if ((String.IsNullOrEmpty(otherString)) || (i == -1)) {
s = new String[2];
s[0] = "1";
s[1] = this;
return s;
}
s = new String[this.Length + 1];
String buffer = this;
int lineCount = 0;
while (i != -1) {
lineCount++;
s[lineCount] = buffer.Substring(0, i);
i += otherString.Length;
if (i < buffer.Length) {
buffer = buffer.Substring(i, buffer.Length);
i = buffer.IndexOf(otherString);
}
else i = -1;
}
lineCount++;
s[lineCount] = buffer;
String t[] = new String[lineCount + 1];
i = 1;
while (i <= lineCount) {
t[i] = s[i];
i++;
}
t[0] = String.Format("%d", lineCount);
return t;
}

String StringMergeArray(String array[], String glue) {
if ((array == null) || (String.IsNullOrEmpty(array[0])) || (array[0].AsInt <= 0)) return null;
if (glue == null) glue = "";
String buffer = "";
int i = 1;
int size = array[0].AsInt;
while (i <= size) {
buffer = buffer.Append(array[i]);
if (i < size) buffer = buffer.Append(glue);
i++;
}
return buffer;
}
#endif

StackData BuildKey(this Stack*) { // returns a 128-bit (16-byte) key for Stack::Copy
String key = "";
int i = 0;
while (i < 16) {
char c = 0;
int j = 7;
while (j >= 0) { // build-a-byte
DateTime *now = DateTime.Now;
bool bit = (Random(now.RawTime) % 2); // returns either 1 or 0
c += (bit << j); // then we shift that bit into place
j--;
}
if (c) {
key = key.AppendChar(c);
i++;
}
}
return key;
}

StackData MaskStacksForCopy(this Stack*) {
// regenerates any existing Stack keys (see BuildKey) when pushing a Stack object (copy) onto this stack
// prevents issues with the data structure
if (String.IsNullOrEmpty(this.Data)) return this.Data;
String s[] = this.Data.SplitByString(StackDataCopyFormat.Substring(0, 18)); // split the data by the stacks within it
if (s[0].AsInt == 1) return this.Data;
int size = s[0].AsInt;
// structure of S will be:
// 1: **STACKDATA:k** - the data type, a stack
// 2: XXXXXXXXXXXXXXXX**DATA - the 128-bit (16-byte) key originally assigned here followed by the stack's data
// 3: XXXXXXXXXXXXXXXX** - the same key
// the rest of StackDataCopyFormat is removed by SplitByString
int i = 2; // start at the first available key
while (i < size) {
String key = this.BuildKey(); // grab a new key
s[i] = key.Append(s[i].Substring(16, s[i].Length)); // replace both instances
s[i + 1] = key.Append(s[i + 1].Substring(16, s[i + 1].Length));
i += 3; // increasing by 3 sets I to the next "2" index in the structure
}
return StringMergeArray(s, StackDataCopyFormat.Substring(0, 18));
}

bool Stack::Push(StackData data, int index) {
if ((index == SCR_NO_VALUE) || (index > this.ItemCount)) index = this.ItemCount;
if ((index < 0) || (data == null)) return false;
if (StackData.IsNullOrEmpty(this.Data)) {
if (String.IsNullOrEmpty(this.Data)) {
this.Data = data;
this.ItemCount++;
return true;
}
StackData items[] = this.GetItemsArray();
if (data.GetType() == eStackDataStack) this.Data = this.MaskStacksForCopy(); // prevent issues if pushing the same stack multiple times
String items[] = this.GetItemsArray();
int size = this.ItemCount;
if (index < size) items[index] = data;
this.Data = this.MergeArray(items);
Expand All @@ -186,18 +279,18 @@ StackData Stack::Pop(bool remove, int index) {
else if (this.PopType == eStackPopRandom) index = Random(this.ItemCount - 1);
}
if ((index < 0) || (index >= this.ItemCount) || (!this.ItemCount) ||
(StackData.IsNullOrEmpty(this.Data))) return null;
StackData items[] = this.GetItemsArray();
(String.IsNullOrEmpty(this.Data))) return null;
String items[] = this.GetItemsArray();
int size = this.ItemCount;
StackData data = items[index];
String data = items[index];
if (remove) {
this.ItemCount--;
if ((!this.ItemCount) || (size == 1)) {
this.Data = null;
items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
return data;
}
StackData buffer[] = new StackData[this.ItemCount];
String buffer[] = new String[this.ItemCount];
int i = 0;
while (i < this.ItemCount) {
if (i < index) buffer[i] = items[i];
Expand All @@ -220,42 +313,23 @@ bool Stack::IsEmpty() {
return (!this.ItemCount);
}

StackData BuildKey(this Stack*) { // returns a 128-bit (16-byte) key for Stack::Copy
StackData key = "";
int i = 0;
while (i < 16) {
char c = 0;
int j = 7;
while (j >= 0) { // build-a-byte
DateTime *now = DateTime.Now;
bool bit = (Random(now.RawTime) % 2); // returns either 1 or 0
c += (bit << j); // then we shift that bit into place
j--;
}
if (c) {
key = key.AppendChar(c);
i++;
}
}
return key;
}

StackData Stack::Copy() {
StackData type = StackData.Format(StackDataFormat, eStackDataStack);
StackData key = this.BuildKey();
StackData stamp = StackData.Format(StackDataCopyFormat, key);
StackData data = this.Data;
String type = String.Format(StackDataFormat, eStackDataStack);
String key = this.BuildKey();
String stamp = String.Format(StackDataCopyFormat, key);
String data = this.Data;
if (data == null) data = "";
return StackData.Format("%s%s%d,%d,%s%s", type, stamp, this.ItemCount, this.PopType, data, stamp);
String s = type.Append(stamp.Append(String.Format("%d,%d,", this.ItemCount, this.PopType)));
return s.Append(data.Append(stamp));
}

bool Stack::LoadFromStack(StackData otherStack) {
if ((otherStack == null) || (otherStack.GetType() != eStackDataStack)) return false;
StackData data = otherStack.Substring(StackDataFormat.Length - 1, otherStack.Length);
StackData stamp = data.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
String data = otherStack.Substring(StackDataFormat.Length - 1, otherStack.Length);
String stamp = data.Substring(0, StackDataCopyFormat.Length + 14); // format + 16 byte key - %s
data = data.Substring(stamp.Length, data.Length);
data = data.Truncate(data.IndexOf(stamp));
StackData buffer = data.Substring(0, data.IndexOf(","));
String buffer = data.Substring(0, data.IndexOf(","));
this.ItemCount = buffer.AsInt;
data = data.Substring(buffer.Length + 1, data.Length);
buffer = data.Substring(0, data.IndexOf(","));
Expand All @@ -272,7 +346,7 @@ bool WriteStack(this File*, StackData stackCopy) {

StackData ReadStackBack(this File*) {
if ((this.Error) || (this.EOF)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
StackData data = this.ReadStringBack();
String data = this.ReadStringBack();
if ((data == null) || (data.GetType() != eStackDataStack) || (this.Error)) AbortGame("File::ReadStackBack: File was not written by File::WriteStack.");
return data;
}
Expand Down
18 changes: 17 additions & 1 deletion Stack.ash
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ AGS v3.1.2+
Defines the current version of the module, formatted as a `float`.
#### Stack_VERSION_130
Defines version 1.3 of the module.
#### Stack_VERSION_120
Defines version 1.2 of the module.
Expand Down Expand Up @@ -358,6 +362,17 @@ CONNECTION WITH THE MODULE OR THE USE OR OTHER DEALINGS IN THE MODULE.
# Changelog
## Version 1.3
Version: 1.3
Author: monkey0506
Date: 21 August 2009
Description: Fixed bug with `String.Format` and large `Stack`s (`String.Format` has a limit on the
size of the `String` it can return; replaced where applicable with `String.Append` instead). Also
added further support to prevent issues with `Stack.Copy`. Previously if you pushed the same stack
copy onto a single stack multiple times there would be problems with the internal data structure.
This should resolve that.
## Version 1.2a
Version: 1.2a
Expand Down Expand Up @@ -389,7 +404,8 @@ Description: First public release.

#ifdef AGS_SUPPORTS_IFVER
#ifver 3.1.2
#define Stack_VERSION 1.2
#define Stack_VERSION 1.3
#define Stack_VERSION_130
#define Stack_VERSION_120
#define Stack_VERSION_100
#endif
Expand Down
2 changes: 1 addition & 1 deletion Stack.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<Name>Stack</Name>
<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>
<Author>monkey0506</Author>
<Version>v1.2a</Version>
<Version>v1.3</Version>
<Key>918333590</Key>
</AGSModule>

0 comments on commit ad1709e

Please sign in to comment.