11
22String StackDataDelimiter;
33String StackDataFormat;
4+ export StackDataFormat; // allow extensions from other scripts
45String StackDataCopyFormat;
5- int StackDataCopyID = 0 ;
66
77StackDataType GetType (this StackData*) {
8+ if (this .Length < (StackDataFormat.Length - 1 )) return eStackDataInvalid;
89 StackData type = this .Substring (0 , StackDataFormat.Length - 1 );
9- return type.Chars [type.IndexOf (" :" ) + 1 ];
10+ int i = type.IndexOf (" :" );
11+ if (i == -1 ) return eStackDataInvalid;
12+ char c = type.Chars [i + 1 ];
13+ if (type != String.Format (StackDataFormat, c)) return eStackDataInvalid;
14+ return c;
1015}
1116
1217int GetAsInt (this StackData*) {
@@ -103,39 +108,32 @@ static StackData Stack::GUIControlToData(GUIControl *theControl) {
103108 return StackData.Format (" %s%d" , type, ((theControl.OwningGUI .ID * AGS_MAX_CONTROLS_PER_GUI) + theControl.ID ));
104109}
105110
106- StackData StackDataMergeArray ( StackData array[]) {
107- if (( array == null) || (StackData. IsNullOrEmpty (array[ 0 ])) || (array[ 0 ]. AsInt <= 0 ) ) return null;
111+ StackData MergeArray ( this Stack*, StackData array[]) {
112+ if (array == null) return null;
108113 StackData glue = StackDataDelimiter;
109114 StackData buffer = " " ;
110- int i = 1 ;
111- int size = array[ 0 ]. AsInt ;
112- while (i <= size) {
115+ int i = 0 ;
116+ int size = this . ItemCount ;
117+ while (i < size) {
113118 buffer = buffer.Append (array[i]);
114- if (i < size) buffer = buffer.Append (glue);
119+ if (i < ( size - 1 ) ) buffer = buffer.Append (glue);
115120 i++;
116121 }
117122 return buffer;
118123}
119124
120- StackData[] SplitDataByItems (this Stack*) {
125+ StackData[] GetItemsArray (this Stack*) {
121126 if (this .Data == null) return null;
122- StackData items[] = new StackData[this .ItemCount + 1 ];
123- items[0 ] = StackData.Format (" %d" , this .ItemCount );
127+ StackData items[] = new StackData[this .ItemCount ];
124128 StackData buffer = this .Data ;
125129 String format = StackDataFormat.Substring (0 , StackDataFormat.IndexOf (" :" ) + 1 );
126130 int i = buffer.IndexOf (format);
127- int j = 1 ;
128- while ((i != -1 ) && (j <= this .ItemCount )) {
131+ int j = 0 ;
132+ while ((i != -1 ) && (j < this .ItemCount )) {
129133 StackDataType type = buffer.Chars [format.Length ];
130134 if (type == eStackDataStack) {
131135 StackData temp = buffer.Substring (StackDataFormat.Length - 1 , buffer.Length );
132- StackData stamp = temp.Substring (0 , StackDataCopyFormat.IndexOf (" :" ) + 1 );
133- i = stamp.Length ;
134- while ((temp.Chars [i] >= ' 0' ) && (temp.Chars [i] <= ' 9' )) {
135- stamp = stamp.AppendChar (temp.Chars [i]);
136- i++;
137- }
138- stamp = stamp.Append (StackDataCopyFormat.Substring (StackDataCopyFormat.IndexOf (" :%d" ) + 3 , StackDataCopyFormat.Length ));
136+ StackData stamp = temp.Substring (0 , StackDataCopyFormat.Length + 14 ); // format + 16 byte key - %s
139137 temp = temp.Substring (stamp.Length , temp.Length );
140138 i = temp.IndexOf (stamp);
141139 if (i != -1 ) items[j] = buffer.Truncate (i + (StackDataFormat.Length - 1 ) + (stamp.Length * 2 ));
@@ -170,12 +168,14 @@ bool Stack::Push(StackData data, int index) {
170168 this .ItemCount ++;
171169 return true ;
172170 }
173- StackData items[] = this .SplitDataByItems ();
174- int size = items[0 ].AsInt ;
175- if (index < size) items[index + 1 ] = data;
176- this .Data = StackDataMergeArray (items);
177- if (index >= size) this .Data = this .Data .Append (StackDataDelimiter.Append (data));
178- this .ItemCount ++;
171+ StackData items[] = this .GetItemsArray ();
172+ int size = this .ItemCount ;
173+ if (index < size) items[index] = data;
174+ this .Data = this .MergeArray (items);
175+ if (index >= size) {
176+ this .Data = this .Data .Append (StackDataDelimiter.Append (data));
177+ this .ItemCount ++;
178+ }
179179 return true ;
180180}
181181
@@ -187,28 +187,26 @@ StackData Stack::Pop(bool remove, int index) {
187187 }
188188 if ((index < 0 ) || (index >= this .ItemCount ) || (!this .ItemCount ) ||
189189 (StackData.IsNullOrEmpty (this .Data ))) return null;
190- StackData items[] = this .SplitDataByItems ();
191- int size = items[0 ].AsInt ;
192- if (index >= size) return null;
193- StackData data = items[index + 1 ];
190+ StackData items[] = this .GetItemsArray ();
191+ int size = this .ItemCount ;
192+ StackData data = items[index];
194193 if (remove) {
195194 this .ItemCount --;
196195 if ((!this .ItemCount ) || (size == 1 )) {
197196 this .Data = null;
198197 items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
199198 return data;
200199 }
201- StackData buffer[] = new StackData[size ];
202- int i = 1 ;
203- while (i < size ) {
204- if (i <= index) buffer[i] = items[i];
200+ StackData buffer[] = new StackData[this . ItemCount ];
201+ int i = 0 ;
202+ while (i < this . ItemCount ) {
203+ if (i < index) buffer[i] = items[i];
205204 else buffer[i] = items[i + 1 ];
206205 i++;
207206 }
208- buffer[0 ] = StackData.Format (" %d" , size - 1 );
209207 items = buffer;
210208 }
211- this .Data = StackDataMergeArray (items);
209+ this .Data = this . MergeArray (items);
212210 items = null; // prevent AGS 3.1.2 bug - Object not in managed pool.
213211 return data;
214212}
@@ -222,10 +220,30 @@ bool Stack::IsEmpty() {
222220 return (!this .ItemCount );
223221}
224222
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+
225243StackData Stack::Copy () {
226244 StackData type = StackData.Format (StackDataFormat, eStackDataStack);
227- StackData stamp = StackData. Format (StackDataCopyFormat, StackDataCopyID );
228- StackDataCopyID++ ;
245+ StackData key = this . BuildKey ( );
246+ StackData stamp = StackData. Format (StackDataCopyFormat, key) ;
229247 StackData data = this .Data ;
230248 if (data == null) data = " " ;
231249 return StackData.Format (" %s%s%d,%d,%s%s" , type, stamp, this .ItemCount , this .PopType , data, stamp);
@@ -234,13 +252,7 @@ StackData Stack::Copy() {
234252bool Stack::LoadFromStack (StackData otherStack) {
235253 if ((otherStack == null) || (otherStack.GetType () != eStackDataStack)) return false ;
236254 StackData data = otherStack.Substring (StackDataFormat.Length - 1 , otherStack.Length );
237- StackData stamp = data.Substring (0 , StackDataCopyFormat.IndexOf (" :" ) + 1 );
238- int i = stamp.Length ;
239- while ((data.Chars [i] >= ' 0' ) && (data.Chars [i] <= ' 9' )) {
240- stamp = stamp.AppendChar (data.Chars [i]);
241- i++;
242- }
243- stamp = stamp.Append (StackDataCopyFormat.Substring (StackDataCopyFormat.IndexOf (" :%d" ) + 3 , StackDataCopyFormat.Length ));
255+ StackData stamp = data.Substring (0 , StackDataCopyFormat.Length + 14 ); // format + 16 byte key - %s
244256 data = data.Substring (stamp.Length , data.Length );
245257 data = data.Truncate (data.IndexOf (stamp));
246258 StackData buffer = data.Substring (0 , data.IndexOf (" ," ));
@@ -252,8 +264,26 @@ bool Stack::LoadFromStack(StackData otherStack) {
252264 return true ;
253265}
254266
267+ bool WriteStack (this File*, StackData stackCopy) {
268+ if ((this .Error ) || (stackCopy == null) || (stackCopy.GetType () != eStackDataStack)) return false ;
269+ this .WriteString (stackCopy);
270+ return (!this .Error );
271+ }
272+
273+ StackData ReadStackBack (this File*) {
274+ if ((this .Error ) || (this .EOF )) AbortGame (" File::ReadStackBack: File was not written by File::WriteStack." );
275+ StackData data = this .ReadStringBack ();
276+ if ((data == null) || (data.GetType () != eStackDataStack) || (this .Error )) AbortGame (" File::ReadStackBack: File was not written by File::WriteStack." );
277+ return data;
278+ }
279+
280+ void Stack::LoadFromFile (File *theFile) {
281+ if ((theFile == null) || (theFile.Error ) || (theFile.EOF )) AbortGame (" Stack::LoadFromFile: File was not written by File::WriteStack." );
282+ this .LoadFromStack (theFile.ReadStackBack ());
283+ }
284+
255285function game_start () {
256286 StackDataDelimiter = " **STACKDATA**" ;
257287 StackDataFormat = " **STACKDATA:%c**" ;
258- StackDataCopyFormat = " **STACKDATA STACK:%d **" ;
288+ StackDataCopyFormat = " **STACKDATA STACK:%s **" ;
259289}
0 commit comments