summaryrefslogtreecommitdiffhomepage
path: root/FoundationEx
diff options
context:
space:
mode:
authormilo24x7@gmail.com <milo24x7@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2013-07-07 20:56:50 +0000
committermilo24x7@gmail.com <milo24x7@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2013-07-07 20:56:50 +0000
commit3b2bf446a7e157788fbe3a9d78acf39bc9550ea0 (patch)
tree97ebddd5aeb57b24803413b834f22dc17c580a06 /FoundationEx
parent10a127c526327da779c88fead87cb00e56d953c4 (diff)
downloadstarshatter-3b2bf446a7e157788fbe3a9d78acf39bc9550ea0.zip
starshatter-3b2bf446a7e157788fbe3a9d78acf39bc9550ea0.tar.gz
starshatter-3b2bf446a7e157788fbe3a9d78acf39bc9550ea0.tar.bz2
Updated open source license declaration and fixed some formatting issues.
Diffstat (limited to 'FoundationEx')
-rw-r--r--FoundationEx/Dictionary.h226
-rw-r--r--FoundationEx/Dictionary.inl544
-rw-r--r--FoundationEx/List.h238
-rw-r--r--FoundationEx/List.inl912
-rw-r--r--FoundationEx/MemDebug.cpp448
-rw-r--r--FoundationEx/MemDebug.h206
-rw-r--r--FoundationEx/Text.cpp1526
-rw-r--r--FoundationEx/Text.h410
-rw-r--r--FoundationEx/ThreadSync.h138
9 files changed, 2432 insertions, 2216 deletions
diff --git a/FoundationEx/Dictionary.h b/FoundationEx/Dictionary.h
index 26ffd2e..8a8c49d 100644
--- a/FoundationEx/Dictionary.h
+++ b/FoundationEx/Dictionary.h
@@ -1,101 +1,125 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: Dictionary.h
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Declaration of the Dictionary class
-*/
-
-#ifndef Dictionary_h
-#define Dictionary_h
-
-#include "Text.h"
-
-// +-------------------------------------------------------------------+
-
-template <class T> class Dictionary;
-template <class T> class DictionaryIter;
-template <class T> class DictionaryCell;
-
-// +-------------------------------------------------------------------+
-
-template <class T> class Dictionary
-{
-public:
- Dictionary();
- ~Dictionary();
-
- T& operator[](const Text& key);
-
- void insert(const Text& key, const T& val);
- void remove(const Text& key);
-
- void clear();
-
- int size() const { return items; }
- int isEmpty() const { return !items; }
-
- int contains(const Text& key) const;
- T find(const Text& key, T defval) const;
-
-private:
- void init();
-
- int items;
-
- typedef DictionaryCell<T>* PTR;
- PTR table[256];
-
- friend class DictionaryIter<T>;
-};
-
-// +-------------------------------------------------------------------+
-
-template <class T> class DictionaryIter
-{
-public:
- DictionaryIter(Dictionary<T>& l);
- ~DictionaryIter();
-
- int operator++(); // prefix
-
- void reset();
- void forth();
-
- Text key() const;
- T value() const;
-
- void attach(Dictionary<T>& l);
- Dictionary<T>& container();
-
-private:
- Dictionary<T>* dict;
- DictionaryCell<T>* here;
- int chain;
-};
-
-// +-------------------------------------------------------------------+
-
-template <class T> class DictionaryCell
-{
-public:
- DictionaryCell(const Text& k) : key(k), value( ), next(0) { }
- DictionaryCell(const Text& k, const T& v) : key(k), value(v), next(0) { }
- ~DictionaryCell() { }
-
- Text key;
- T value;
- DictionaryCell<T>* next;
-};
-
-// +-------------------------------------------------------------------+
-
-#include "Dictionary.inl"
-#endif Dictionary_h
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: Dictionary.h
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Declaration of the Dictionary class
+*/
+
+#ifndef Dictionary_h
+#define Dictionary_h
+
+#include "Text.h"
+
+// +-------------------------------------------------------------------+
+
+template <class T> class Dictionary;
+template <class T> class DictionaryIter;
+template <class T> class DictionaryCell;
+
+// +-------------------------------------------------------------------+
+
+template <class T> class Dictionary
+{
+public:
+ Dictionary();
+ ~Dictionary();
+
+ T& operator[](const Text& key);
+
+ void insert(const Text& key, const T& val);
+ void remove(const Text& key);
+
+ void clear();
+
+ int size() const { return items; }
+ int isEmpty() const { return !items; }
+
+ int contains(const Text& key) const;
+ T find(const Text& key, T defval) const;
+
+private:
+ void init();
+
+ int items;
+
+ typedef DictionaryCell<T>* PTR;
+ PTR table[256];
+
+ friend class DictionaryIter<T>;
+};
+
+// +-------------------------------------------------------------------+
+
+template <class T> class DictionaryIter
+{
+public:
+ DictionaryIter(Dictionary<T>& l);
+ ~DictionaryIter();
+
+ int operator++(); // prefix
+
+ void reset();
+ void forth();
+
+ Text key() const;
+ T value() const;
+
+ void attach(Dictionary<T>& l);
+ Dictionary<T>& container();
+
+private:
+ Dictionary<T>* dict;
+ DictionaryCell<T>* here;
+ int chain;
+};
+
+// +-------------------------------------------------------------------+
+
+template <class T> class DictionaryCell
+{
+public:
+ DictionaryCell(const Text& k) : key(k), value( ), next(0) { }
+ DictionaryCell(const Text& k, const T& v) : key(k), value(v), next(0) { }
+ ~DictionaryCell() { }
+
+ Text key;
+ T value;
+ DictionaryCell<T>* next;
+};
+
+// +-------------------------------------------------------------------+
+
+#include "Dictionary.inl"
+#endif Dictionary_h
+
diff --git a/FoundationEx/Dictionary.inl b/FoundationEx/Dictionary.inl
index 98cdd05..1f32b9a 100644
--- a/FoundationEx/Dictionary.inl
+++ b/FoundationEx/Dictionary.inl
@@ -1,260 +1,284 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: Dictionary.inl
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Implementation of the Dictionary class
-*/
-
-#ifndef NDEBUG
-#define DICT_CHECK(a, b) if ((a) == 0) throw b;
-#else
-#define DICT_CHECK(a, b)
-#endif
-
-const int CHAINS = 256;
-
-// +-------------------------------------------------------------------+
-
-template <class T> Dictionary<T>::Dictionary()
- : items(0)
-{ init(); }
-
-template <class T> Dictionary<T>::~Dictionary()
-{ clear(); }
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void Dictionary<T>::init()
-{
- items = 0;
- memset(table, 0, CHAINS*sizeof(PTR));
-}
-
-template <class T>
-void Dictionary<T>::clear()
-{
- for (int i = 0; i < CHAINS; i++) {
- DictionaryCell<T>* link = table[i];
-
- while (link) {
- DictionaryCell<T>* n = link->next;
- delete link;
- link = n;
- }
- }
-
- init();
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T& Dictionary<T>::operator[](const Text& key)
-{
- int idx = key.hash() % CHAINS;
- DictionaryCell<T>* cell = table[idx];
-
- if (cell == 0) { // empty chain
- items++;
-
-#ifdef MEM_DEBUG
- cell = new(__FILE__,__LINE__) DictionaryCell<T>(key);
-#else
- cell = new DictionaryCell<T>(key);
-#endif
-
- table[idx] = cell;
-
- return cell->value;
- }
- else { // search for key
- while (cell->next && cell->key != key)
- cell = cell->next;
-
- if (cell->key != key) { // not found in chain
- items++;
-
-#ifdef MEM_DEBUG
- cell->next = new(__FILE__,__LINE__) DictionaryCell<T>(key);
-#else
- cell->next = new DictionaryCell<T>(key);
-#endif
-
- return cell->next->value;
- }
- else { // found: return it!
- return cell->value;
- }
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void Dictionary<T>::insert(const Text& key, const T& val)
-{
- T& value = operator[](key);
- value = val;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void Dictionary<T>::remove(const Text& key)
-{
- int idx = key.hash() % CHAINS;
- DictionaryCell<T>* cell = table[idx];
-
- if (cell == 0) { // empty chain
- return;
- }
- else { // search for key
- while (cell->next && cell->key != key)
- cell = cell->next;
-
- if (cell->key != key) { // not found in chain
- return;
- }
- else { // found: remove it!
- if (table[idx] == cell) {
- table[idx] = cell->next;
- delete cell;
- }
- else {
- DictionaryCell<T>* p = table[idx];
- while (p->next != cell)
- p = p->next;
- p->next = cell->next;
- delete cell;
- }
- }
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-int Dictionary<T>::contains(const Text& key) const
-{
- int idx = key.hash() % CHAINS;
- DictionaryCell<T>* cell = table[idx];
-
- if (cell != 0) {
- while (cell->next && cell->key != key)
- cell = cell->next;
-
- if (cell->key == key)
- return 1;
- }
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T Dictionary<T>::find(const Text& key, T defval) const
-{
- int idx = key.hash() % CHAINS;
- DictionaryCell<T>* cell = table[idx];
-
- if (cell != 0) {
- while (cell->next && cell->key != key)
- cell = cell->next;
-
- if (cell->key == key)
- return cell->value;
- }
-
- return defval;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T> DictionaryIter<T>::DictionaryIter(Dictionary<T>& d)
- : dict(&d), chain(0), here(0)
-{ }
-
-template <class T> DictionaryIter<T>::~DictionaryIter()
-{ }
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void DictionaryIter<T>::reset()
-{
- chain = 0;
- here = 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-Text DictionaryIter<T>::key() const
-{
- return here->key;
-}
-
-template <class T>
-T DictionaryIter<T>::value() const
-{
- return here->value;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-int DictionaryIter<T>::operator++()
-{
- forth();
- int more = chain < CHAINS;
- return more;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void DictionaryIter<T>::forth()
-{
- if (here) {
- here = here->next;
- if (!here) // off the end of this chain
- chain++;
- }
-
- if (!here) {
- while (!dict->table[chain] && chain < CHAINS)
- chain++;
-
- if (chain < CHAINS)
- here = dict->table[chain];
- else
- here = 0;
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void DictionaryIter<T>::attach(Dictionary<T>& d)
-{
- dict = &d;
- reset();
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-Dictionary<T>& DictionaryIter<T>::container()
-{
- return *dict;
-}
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: Dictionary.inl
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Implementation of the Dictionary class
+*/
+
+#ifndef NDEBUG
+#define DICT_CHECK(a, b) if ((a) == 0) throw b;
+#else
+#define DICT_CHECK(a, b)
+#endif
+
+const int CHAINS = 256;
+
+// +-------------------------------------------------------------------+
+
+template <class T> Dictionary<T>::Dictionary()
+ : items(0)
+{ init(); }
+
+template <class T> Dictionary<T>::~Dictionary()
+{ clear(); }
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void Dictionary<T>::init()
+{
+ items = 0;
+ memset(table, 0, CHAINS*sizeof(PTR));
+}
+
+template <class T>
+void Dictionary<T>::clear()
+{
+ for (int i = 0; i < CHAINS; i++) {
+ DictionaryCell<T>* link = table[i];
+
+ while (link) {
+ DictionaryCell<T>* n = link->next;
+ delete link;
+ link = n;
+ }
+ }
+
+ init();
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T& Dictionary<T>::operator[](const Text& key)
+{
+ int idx = key.hash() % CHAINS;
+ DictionaryCell<T>* cell = table[idx];
+
+ if (cell == 0) { // empty chain
+ items++;
+
+#ifdef MEM_DEBUG
+ cell = new(__FILE__,__LINE__) DictionaryCell<T>(key);
+#else
+ cell = new DictionaryCell<T>(key);
+#endif
+
+ table[idx] = cell;
+
+ return cell->value;
+ }
+ else { // search for key
+ while (cell->next && cell->key != key)
+ cell = cell->next;
+
+ if (cell->key != key) { // not found in chain
+ items++;
+
+#ifdef MEM_DEBUG
+ cell->next = new(__FILE__,__LINE__) DictionaryCell<T>(key);
+#else
+ cell->next = new DictionaryCell<T>(key);
+#endif
+
+ return cell->next->value;
+ }
+ else { // found: return it!
+ return cell->value;
+ }
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void Dictionary<T>::insert(const Text& key, const T& val)
+{
+ T& value = operator[](key);
+ value = val;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void Dictionary<T>::remove(const Text& key)
+{
+ int idx = key.hash() % CHAINS;
+ DictionaryCell<T>* cell = table[idx];
+
+ if (cell == 0) { // empty chain
+ return;
+ }
+ else { // search for key
+ while (cell->next && cell->key != key)
+ cell = cell->next;
+
+ if (cell->key != key) { // not found in chain
+ return;
+ }
+ else { // found: remove it!
+ if (table[idx] == cell) {
+ table[idx] = cell->next;
+ delete cell;
+ }
+ else {
+ DictionaryCell<T>* p = table[idx];
+ while (p->next != cell)
+ p = p->next;
+ p->next = cell->next;
+ delete cell;
+ }
+ }
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+int Dictionary<T>::contains(const Text& key) const
+{
+ int idx = key.hash() % CHAINS;
+ DictionaryCell<T>* cell = table[idx];
+
+ if (cell != 0) {
+ while (cell->next && cell->key != key)
+ cell = cell->next;
+
+ if (cell->key == key)
+ return 1;
+ }
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T Dictionary<T>::find(const Text& key, T defval) const
+{
+ int idx = key.hash() % CHAINS;
+ DictionaryCell<T>* cell = table[idx];
+
+ if (cell != 0) {
+ while (cell->next && cell->key != key)
+ cell = cell->next;
+
+ if (cell->key == key)
+ return cell->value;
+ }
+
+ return defval;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T> DictionaryIter<T>::DictionaryIter(Dictionary<T>& d)
+ : dict(&d), chain(0), here(0)
+{ }
+
+template <class T> DictionaryIter<T>::~DictionaryIter()
+{ }
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void DictionaryIter<T>::reset()
+{
+ chain = 0;
+ here = 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+Text DictionaryIter<T>::key() const
+{
+ return here->key;
+}
+
+template <class T>
+T DictionaryIter<T>::value() const
+{
+ return here->value;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+int DictionaryIter<T>::operator++()
+{
+ forth();
+ int more = chain < CHAINS;
+ return more;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void DictionaryIter<T>::forth()
+{
+ if (here) {
+ here = here->next;
+ if (!here) // off the end of this chain
+ chain++;
+ }
+
+ if (!here) {
+ while (!dict->table[chain] && chain < CHAINS)
+ chain++;
+
+ if (chain < CHAINS)
+ here = dict->table[chain];
+ else
+ here = 0;
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void DictionaryIter<T>::attach(Dictionary<T>& d)
+{
+ dict = &d;
+ reset();
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+Dictionary<T>& DictionaryIter<T>::container()
+{
+ return *dict;
+}
+
diff --git a/FoundationEx/List.h b/FoundationEx/List.h
index 1460cf4..13a48cd 100644
--- a/FoundationEx/List.h
+++ b/FoundationEx/List.h
@@ -1,107 +1,131 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: List.h
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Declaration of the List class template
-*/
-
-#ifndef List_h
-#define List_h
-
-// +-------------------------------------------------------------------+
-
-template <class T> class List;
-template <class T> class ListIter;
-
-// +-------------------------------------------------------------------+
-
-template <class T> class List
-{
-public:
- List() : items(0), extent(0), array(0) { }
- List(const List<T>& l);
- ~List() { delete [] array; }
-
- T*& operator[](int i);
- T* operator[](int i) const;
- T*& at(int i);
- T* at(int i) const;
-
- void append(List<T>& list);
- void append(const T* val);
- void insert(const T* val, int index=0);
- void insertSort(const T* val);
-
- T* first() const { return operator[](0); }
- T* last() const { return operator[](items-1); }
- T* remove(const T* val);
- T* removeIndex(int index);
-
- void clear();
- void destroy();
-
- int size() const { return items; }
- bool isEmpty() const { return !items; }
-
- bool contains(const T* val) const;
- int count(const T* val) const;
- int index(const T* val) const;
- T* find(const T* val) const;
-
- void sort();
- void shuffle();
-
-private:
- typedef T* PTR;
- void qsort(T** a, int lo, int hi);
- void resize(int newsize);
- bool check(int& index) const;
- void swap(T** a, int i, int j);
-
- int items;
- int extent;
- PTR* array;
-
- friend class ListIter<T>;
-};
-
-// +-------------------------------------------------------------------+
-
-template <class T> class ListIter
-{
-public:
- ListIter() : list(0), step(-1) { }
- ListIter(const ListIter<T>& i) : list(i.list), step(i.step) { }
- ListIter(List<T>& l) : list(&l), step(-1) { }
-
- int operator++() { return next() != 0; }
- int operator--() { return prev() != 0; }
- T* operator->() { return value(); }
- T& operator* () { return *value(); }
-
- void reset() { step = -1; }
- T* next();
- T* prev();
- T* value();
- T* removeItem();
-
- void attach(List<T>& l);
- List<T>& container();
- int size();
- int index() { return step; }
-
-private:
- List<T>* list;
- int step;
-};
-
-#include "List.inl"
-#endif List_h
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: List.h
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Declaration of the List class template
+*/
+
+#ifndef List_h
+#define List_h
+
+// +-------------------------------------------------------------------+
+
+template <class T> class List;
+template <class T> class ListIter;
+
+// +-------------------------------------------------------------------+
+
+template <class T> class List
+{
+public:
+ List() : items(0), extent(0), array(0) { }
+ List(const List<T>& l);
+ ~List() { delete [] array; }
+
+ T*& operator[](int i);
+ T* operator[](int i) const;
+ T*& at(int i);
+ T* at(int i) const;
+
+ void append(List<T>& list);
+ void append(const T* val);
+ void insert(const T* val, int index=0);
+ void insertSort(const T* val);
+
+ T* first() const { return operator[](0); }
+ T* last() const { return operator[](items-1); }
+ T* remove(const T* val);
+ T* removeIndex(int index);
+
+ void clear();
+ void destroy();
+
+ int size() const { return items; }
+ bool isEmpty() const { return !items; }
+
+ bool contains(const T* val) const;
+ int count(const T* val) const;
+ int index(const T* val) const;
+ T* find(const T* val) const;
+
+ void sort();
+ void shuffle();
+
+private:
+ typedef T* PTR;
+ void qsort(T** a, int lo, int hi);
+ void resize(int newsize);
+ bool check(int& index) const;
+ void swap(T** a, int i, int j);
+
+ int items;
+ int extent;
+ PTR* array;
+
+ friend class ListIter<T>;
+};
+
+// +-------------------------------------------------------------------+
+
+template <class T> class ListIter
+{
+public:
+ ListIter() : list(0), step(-1) { }
+ ListIter(const ListIter<T>& i) : list(i.list), step(i.step) { }
+ ListIter(List<T>& l) : list(&l), step(-1) { }
+
+ int operator++() { return next() != 0; }
+ int operator--() { return prev() != 0; }
+ T* operator->() { return value(); }
+ T& operator* () { return *value(); }
+
+ void reset() { step = -1; }
+ T* next();
+ T* prev();
+ T* value();
+ T* removeItem();
+
+ void attach(List<T>& l);
+ List<T>& container();
+ int size();
+ int index() { return step; }
+
+private:
+ List<T>* list;
+ int step;
+};
+
+#include "List.inl"
+#endif List_h
+
diff --git a/FoundationEx/List.inl b/FoundationEx/List.inl
index 0dd6134..7f552c4 100644
--- a/FoundationEx/List.inl
+++ b/FoundationEx/List.inl
@@ -1,444 +1,468 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: List.inl
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Implementation of the List class template
-*/
-
-// +-------------------------------------------------------------------+
-
-void Print(const char* fmt, ...);
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-List<T>::List(const List<T>& l)
- : items(l.items), extent(l.extent)
-{
-#ifdef MEM_DEBUG
- array = new(__FILE__,__LINE__) PTR[extent];
-#else
- array = new PTR[extent];
-#endif
-
- for (int i = 0; i < extent; i++)
- array[i] = l.array[i];
-}
-
-template <class T>
-void List<T>::clear()
-{
- delete [] array;
- items = 0;
- extent = 0;
- array = 0;
-}
-
-template <class T>
-void List<T>::destroy()
-{
- if (items) {
- items = 0; // prevent dangerous re-entrancy
-
- for (int i = 0; i < extent; i++)
- delete array[i];
-
- delete [] array;
- items = 0;
- extent = 0;
- array = 0;
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-bool List<T>::check(int& index) const
-{
- if (index < 0) {
- Print("Bounds error in List(%08x) T=%s index=%d min=0\n", (int)this, T::TYPENAME(), index);
- index = 0;
- }
-
- else if (index >= items) {
- Print("Bounds error in List(%08x) T=%s index=%d max=%d\n", (int)this, T::TYPENAME(), index, items-1);
- index = items-1;
- }
-
- return (index >= 0 && index < items);
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T*& List<T>::operator[](int index)
-{
- if (check(index))
- return array[index];
-
- if (!array || !extent)
- resize(1);
-
- return array[0];
-}
-
-template <class T>
-T* List<T>::operator[](int index) const
-{
- if (check(index))
- return array[index];
- return 0;
-}
-
-template <class T>
-T*& List<T>::at(int index)
-{
- if (check(index))
- return array[index];
-
- if (!array || !extent)
- resize(1);
-
- return array[0];
-}
-
-template <class T>
-T* List<T>::at(int index) const
-{
- if (check(index))
- return array[index];
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void List<T>::resize(int newsize)
-{
- if (newsize > extent) {
- extent = 16 * (newsize/16 + 1);
-
-#ifdef MEM_DEBUG
- T** v = new(__FILE__,__LINE__) PTR[extent];
-#else
- T** v = new PTR[extent];
-#endif
- int i;
- for (i = 0; i < items; i++)
- v[i] = array[i];
-
- for (; i < extent; i++)
- v[i] = 0;
-
- delete [] array;
- array = v;
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void List<T>::append(const T* item)
-{
- if (item) {
- if (items+1 > extent) resize(items+1);
- array[items++] = (T*)item;
- }
-}
-
-template <class T>
-void List<T>::append(List<T>& list)
-{
- if (&list != this && list.items > 0) {
- int need = items + list.items;
- if (need > extent) resize(need);
-
- for (int i = 0; i < list.items; i++)
- array[items++] = list.array[i];
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void List<T>::insert(const T* item, int index)
-{
- if (item && index >= 0 && index <= items) {
- if (items+1 > extent) resize(items+1);
-
- // slide right:
- for (int i = items; i > index; i--)
- array[i] = array[i-1];
-
- array[index] = (T*)item;
- items++;
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void List<T>::insertSort(const T* item)
-{
- if (item) {
- int i;
- for (i = 0; i < items; i++) {
- if (*item < *array[i])
- break;
- }
-
- insert(item, i);
- }
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T* List<T>::remove(const T* val)
-{
- if (items == 0 || val == 0)
- return 0;
-
- for (int i = 0; i < items; i++) {
- if (array[i] == val) {
- return removeIndex(i);
- }
- }
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T* List<T>::removeIndex(int index)
-{
- if (!check(index))
- return 0;
-
- T* tmp = array[index];
- array[index] = 0;
-
- // slide left:
- for (int i = index; i < items-1; i++)
- array[i] = array[i+1];
-
- // blank out the hole we just created:
- array[items-1] = 0;
-
- items--;
- return tmp;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-bool List<T>::contains(const T* val) const
-{
- if (val) {
- if (index(val) != -1)
- return true;
- }
-
- return false;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-int List<T>::count(const T* val) const
-{
- int c = 0;
-
- if (val) {
- for (int i = 0; i < items; i++) {
- if (array[i] && ((*array[i])==(*val)))
- c++;
- }
- }
-
- return c;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-int List<T>::index(const T* val) const
-{
- if (val) {
- for (int i = 0; i < items; i++) {
- if (array[i] && ((*array[i])==(*val)))
- return i;
- }
- }
-
- return -1;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T* List<T>::find(const T* val) const
-{
- if (val) {
- for (int i = 0; i < items; i++) {
- if (array[i] && ((*array[i])==(*val)))
- return array[i];
- }
- }
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void List<T>::swap(T** a, int i, int j)
-{
- if (i >= 0 && i < items && j >= 0 && j < items && i != j) {
- T* t = a[i];
- a[i] = a[j];
- a[j] = t;
- }
-}
-
-template <class T>
-void List<T>::qsort(T** a, int lo0, int hi0)
-{
- int lo = lo0;
- int hi = hi0;
-
- // zero or one element list, nothing to do:
- if (lo >= hi) {
- return;
- }
-
- // two element list, swap if needed:
- else if (lo == hi-1) {
- if (*a[hi] < *a[lo]) {
- swap(a, lo, hi);
- }
- return;
- }
-
- // pick a pivot, and move it out of the way:
- int mid = (lo+hi)/2;
- T* pivot = a[mid];
- a[mid] = a[hi];
- a[hi] = pivot;
-
- while (lo < hi) {
- while ((*a[lo] <= *pivot) && lo < hi) lo++;
- while ((*pivot <= *a[hi]) && lo < hi) hi--;
-
- if (lo < hi) {
- swap(a, lo, hi);
- }
- }
-
- // Put the pivot into its final location:
- a[hi0] = a[hi];
- a[hi] = pivot;
-
- qsort(a, lo0, lo-1);
- qsort(a, hi+1, hi0);
-}
-
-template <class T>
-void List<T>::sort()
-{
- if (items < 2)
- return;
-
- qsort(array, 0, items-1);
-}
-
-template <class T>
-void List<T>::shuffle()
-{
- if (items < 3)
- return;
-
- for (int s = 0; s < 5; s++) {
- for (int i = 0; i < items; i++) {
- int j = (rand()>>4) % items;
- swap(array, i, j);
- }
- }
-}
-
-// +===================================================================+
-
-template <class T>
-T* ListIter<T>::value()
-{
- if (list && step >= 0 && step < list->items)
- return list->array[step];
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T* ListIter<T>::removeItem()
-{
- if (list && step >= 0 && step < list->items)
- return list->removeIndex(step--);
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-T* ListIter<T>::next()
-{
- if (list && step >= -1 && step < list->items-1)
- return list->array[++step];
-
- return 0;
-}
-
-template <class T>
-T* ListIter<T>::prev()
-{
- if (list && step > 0 && step < list->items)
- return list->array[--step];
-
- return 0;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-void ListIter<T>::attach(List<T>& l)
-{
- list = &l;
- step = -1;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-int ListIter<T>::size()
-{
- if (!list) return 0;
- return list->items;
-}
-
-// +-------------------------------------------------------------------+
-
-template <class T>
-List<T>& ListIter<T>::container()
-{
- return *list;
-}
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: List.inl
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Implementation of the List class template
+*/
+
+// +-------------------------------------------------------------------+
+
+void Print(const char* fmt, ...);
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+List<T>::List(const List<T>& l)
+ : items(l.items), extent(l.extent)
+{
+#ifdef MEM_DEBUG
+ array = new(__FILE__,__LINE__) PTR[extent];
+#else
+ array = new PTR[extent];
+#endif
+
+ for (int i = 0; i < extent; i++)
+ array[i] = l.array[i];
+}
+
+template <class T>
+void List<T>::clear()
+{
+ delete [] array;
+ items = 0;
+ extent = 0;
+ array = 0;
+}
+
+template <class T>
+void List<T>::destroy()
+{
+ if (items) {
+ items = 0; // prevent dangerous re-entrancy
+
+ for (int i = 0; i < extent; i++)
+ delete array[i];
+
+ delete [] array;
+ items = 0;
+ extent = 0;
+ array = 0;
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+bool List<T>::check(int& index) const
+{
+ if (index < 0) {
+ Print("Bounds error in List(%08x) T=%s index=%d min=0\n", (int)this, T::TYPENAME(), index);
+ index = 0;
+ }
+
+ else if (index >= items) {
+ Print("Bounds error in List(%08x) T=%s index=%d max=%d\n", (int)this, T::TYPENAME(), index, items-1);
+ index = items-1;
+ }
+
+ return (index >= 0 && index < items);
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T*& List<T>::operator[](int index)
+{
+ if (check(index))
+ return array[index];
+
+ if (!array || !extent)
+ resize(1);
+
+ return array[0];
+}
+
+template <class T>
+T* List<T>::operator[](int index) const
+{
+ if (check(index))
+ return array[index];
+ return 0;
+}
+
+template <class T>
+T*& List<T>::at(int index)
+{
+ if (check(index))
+ return array[index];
+
+ if (!array || !extent)
+ resize(1);
+
+ return array[0];
+}
+
+template <class T>
+T* List<T>::at(int index) const
+{
+ if (check(index))
+ return array[index];
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void List<T>::resize(int newsize)
+{
+ if (newsize > extent) {
+ extent = 16 * (newsize/16 + 1);
+
+#ifdef MEM_DEBUG
+ T** v = new(__FILE__,__LINE__) PTR[extent];
+#else
+ T** v = new PTR[extent];
+#endif
+ int i;
+ for (i = 0; i < items; i++)
+ v[i] = array[i];
+
+ for (; i < extent; i++)
+ v[i] = 0;
+
+ delete [] array;
+ array = v;
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void List<T>::append(const T* item)
+{
+ if (item) {
+ if (items+1 > extent) resize(items+1);
+ array[items++] = (T*)item;
+ }
+}
+
+template <class T>
+void List<T>::append(List<T>& list)
+{
+ if (&list != this && list.items > 0) {
+ int need = items + list.items;
+ if (need > extent) resize(need);
+
+ for (int i = 0; i < list.items; i++)
+ array[items++] = list.array[i];
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void List<T>::insert(const T* item, int index)
+{
+ if (item && index >= 0 && index <= items) {
+ if (items+1 > extent) resize(items+1);
+
+ // slide right:
+ for (int i = items; i > index; i--)
+ array[i] = array[i-1];
+
+ array[index] = (T*)item;
+ items++;
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void List<T>::insertSort(const T* item)
+{
+ if (item) {
+ int i;
+ for (i = 0; i < items; i++) {
+ if (*item < *array[i])
+ break;
+ }
+
+ insert(item, i);
+ }
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T* List<T>::remove(const T* val)
+{
+ if (items == 0 || val == 0)
+ return 0;
+
+ for (int i = 0; i < items; i++) {
+ if (array[i] == val) {
+ return removeIndex(i);
+ }
+ }
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T* List<T>::removeIndex(int index)
+{
+ if (!check(index))
+ return 0;
+
+ T* tmp = array[index];
+ array[index] = 0;
+
+ // slide left:
+ for (int i = index; i < items-1; i++)
+ array[i] = array[i+1];
+
+ // blank out the hole we just created:
+ array[items-1] = 0;
+
+ items--;
+ return tmp;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+bool List<T>::contains(const T* val) const
+{
+ if (val) {
+ if (index(val) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+int List<T>::count(const T* val) const
+{
+ int c = 0;
+
+ if (val) {
+ for (int i = 0; i < items; i++) {
+ if (array[i] && ((*array[i])==(*val)))
+ c++;
+ }
+ }
+
+ return c;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+int List<T>::index(const T* val) const
+{
+ if (val) {
+ for (int i = 0; i < items; i++) {
+ if (array[i] && ((*array[i])==(*val)))
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T* List<T>::find(const T* val) const
+{
+ if (val) {
+ for (int i = 0; i < items; i++) {
+ if (array[i] && ((*array[i])==(*val)))
+ return array[i];
+ }
+ }
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void List<T>::swap(T** a, int i, int j)
+{
+ if (i >= 0 && i < items && j >= 0 && j < items && i != j) {
+ T* t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+}
+
+template <class T>
+void List<T>::qsort(T** a, int lo0, int hi0)
+{
+ int lo = lo0;
+ int hi = hi0;
+
+ // zero or one element list, nothing to do:
+ if (lo >= hi) {
+ return;
+ }
+
+ // two element list, swap if needed:
+ else if (lo == hi-1) {
+ if (*a[hi] < *a[lo]) {
+ swap(a, lo, hi);
+ }
+ return;
+ }
+
+ // pick a pivot, and move it out of the way:
+ int mid = (lo+hi)/2;
+ T* pivot = a[mid];
+ a[mid] = a[hi];
+ a[hi] = pivot;
+
+ while (lo < hi) {
+ while ((*a[lo] <= *pivot) && lo < hi) lo++;
+ while ((*pivot <= *a[hi]) && lo < hi) hi--;
+
+ if (lo < hi) {
+ swap(a, lo, hi);
+ }
+ }
+
+ // Put the pivot into its final location:
+ a[hi0] = a[hi];
+ a[hi] = pivot;
+
+ qsort(a, lo0, lo-1);
+ qsort(a, hi+1, hi0);
+}
+
+template <class T>
+void List<T>::sort()
+{
+ if (items < 2)
+ return;
+
+ qsort(array, 0, items-1);
+}
+
+template <class T>
+void List<T>::shuffle()
+{
+ if (items < 3)
+ return;
+
+ for (int s = 0; s < 5; s++) {
+ for (int i = 0; i < items; i++) {
+ int j = (rand()>>4) % items;
+ swap(array, i, j);
+ }
+ }
+}
+
+// +===================================================================+
+
+template <class T>
+T* ListIter<T>::value()
+{
+ if (list && step >= 0 && step < list->items)
+ return list->array[step];
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T* ListIter<T>::removeItem()
+{
+ if (list && step >= 0 && step < list->items)
+ return list->removeIndex(step--);
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+T* ListIter<T>::next()
+{
+ if (list && step >= -1 && step < list->items-1)
+ return list->array[++step];
+
+ return 0;
+}
+
+template <class T>
+T* ListIter<T>::prev()
+{
+ if (list && step > 0 && step < list->items)
+ return list->array[--step];
+
+ return 0;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+void ListIter<T>::attach(List<T>& l)
+{
+ list = &l;
+ step = -1;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+int ListIter<T>::size()
+{
+ if (!list) return 0;
+ return list->items;
+}
+
+// +-------------------------------------------------------------------+
+
+template <class T>
+List<T>& ListIter<T>::container()
+{
+ return *list;
+}
+
diff --git a/FoundationEx/MemDebug.cpp b/FoundationEx/MemDebug.cpp
index 7ed2958..2694b33 100644
--- a/FoundationEx/MemDebug.cpp
+++ b/FoundationEx/MemDebug.cpp
@@ -1,212 +1,236 @@
-/* Project nGen
- John DiCamillo
- Copyright © 1997-2001. All Rights Reserved.
-
- SUBSYSTEM: foundation
- FILE: MemDebug.cpp
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Memory Debugging class
-*/
-
-#include "MemDebug.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <crtdbg.h>
-#include <malloc.h>
-
-// +--------------------------------------------------------------------+
-
-static Memory::LEVEL mem_chk_level = Memory::PERIODIC;
-
-#ifdef _DEBUG
-static _CrtMemState mem_chk_p1,
- mem_chk_p2;
-#endif
-
-static HANDLE mem_log_file = 0;
-
-// +--------------------------------------------------------------------+
-
-#ifdef _DEBUG
-#define CrtSetDebugField(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
-#define CrtClrDebugField(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
-#endif
-
-static void heapdump()
-{
- _HEAPINFO hinfo;
- int heapstatus;
- DWORD used = 0;
- DWORD avail = 0;
- char report[256];
-
- hinfo._pentry = NULL;
- while ((heapstatus = _heapwalk( &hinfo )) == _HEAPOK) {
- sprintf_s(report, "%6s block at %Fp of size %4.4X\n",
- ( hinfo._useflag == _USEDENTRY ? "USED" : "FREE" ),
- hinfo._pentry, hinfo._size);
-
- _RPT0(_CRT_WARN, report);
-
- if (hinfo._useflag == _USEDENTRY)
- used += hinfo._size;
- else
- avail += hinfo._size;
- }
-
- sprintf_s(report, "------\nUsed Blocks: %d\nAvail Blocks: %d\nTotal Blocks: %d\n", used, avail, used+avail); //-V576
- _RPT0(_CRT_WARN, report);
-
- switch (heapstatus) {
- case _HEAPEMPTY:
- _RPT0(_CRT_WARN, "OK - empty heap\n" );
- break;
- case _HEAPEND:
- _RPT0(_CRT_WARN, "OK - end of heap\n" );
- break;
- case _HEAPBADPTR:
- _RPT0(_CRT_WARN, "ERROR - bad pointer to heap\n" );
- break;
- case _HEAPBADBEGIN:
- _RPT0(_CRT_WARN, "ERROR - bad start of heap\n" );
- break;
- case _HEAPBADNODE:
- _RPT0(_CRT_WARN, "ERROR - bad node in heap\n" );
- break;
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::OpenLog(const char* filename)
-{
-#ifdef _DEBUG
- if (!filename || !strlen(filename))
- filename = "memdbg.txt";
-
- mem_log_file = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
-
- if (mem_log_file) {
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_WARN, mem_log_file);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_ERROR, mem_log_file);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_ASSERT, mem_log_file);
- }
-
- _CrtMemCheckpoint(&mem_chk_p1);
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::CloseLog()
-{
-#ifdef _DEBUG
- if (mem_log_file) {
- CloseHandle(mem_log_file);
- mem_log_file = 0;
-
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
- }
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::Check()
-{
-#ifdef _DEBUG
- if (! _CrtCheckMemory()) {
- _RPT0(_CRT_ERROR, "\n\nMemory Check Failed.\n");
- heapdump();
- Checkpoint();
- _asm { int 3 }
- exit(1111);
- }
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::Checkpoint()
-{
-#ifdef _DEBUG
- if (mem_chk_level < PERIODIC) return;
-
- _RPT0(_CRT_WARN, "\n\nMemory Checkpoint:\n"
- "--------------------------------------------------\n");
-
- _CrtMemState s;
- _CrtMemCheckpoint(&mem_chk_p2);
- _CrtMemDifference(&s, &mem_chk_p1, &mem_chk_p2);
- _CrtMemDumpStatistics(&s);
-
- memcpy(&mem_chk_p1, &mem_chk_p2, sizeof(mem_chk_p1));
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::Stats()
-{
-#ifdef _DEBUG
- if (mem_chk_level < PERIODIC) return;
-
- _RPT0(_CRT_WARN, "\n\nMemory Stats:\n"
- "--------------------------------------------------\n");
-
- _CrtMemState s;
- _CrtMemCheckpoint(&s);
- _CrtMemDumpStatistics(&s);
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::DumpLeaks()
-{
-#ifdef _DEBUG
- _RPT0(_CRT_WARN, "\n\nMemory Dump Leaks:\n"
- "--------------------------------------------------\n");
- _CrtDumpMemoryLeaks();
-#endif
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Memory::SetLevel(LEVEL l)
-{
-#ifdef _DEBUG
- mem_chk_level = l;
-
- _CrtSetDbgFlag(0);
-
- switch (mem_chk_level) {
- case MAXIMAL: CrtSetDebugField(_CRTDBG_CHECK_ALWAYS_DF);
- case PERIODIC: CrtSetDebugField(_CRTDBG_DELAY_FREE_MEM_DF);
- case LEAKS: CrtSetDebugField(_CRTDBG_LEAK_CHECK_DF);
- case OFF:
- default: break;
- }
-#endif
-}
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: foundation
+ FILE: MemDebug.cpp
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Memory Debugging class
+*/
+
+#include "MemDebug.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <crtdbg.h>
+#include <malloc.h>
+
+// +--------------------------------------------------------------------+
+
+static Memory::LEVEL mem_chk_level = Memory::PERIODIC;
+
+#ifdef _DEBUG
+static _CrtMemState mem_chk_p1,
+ mem_chk_p2;
+#endif
+
+static HANDLE mem_log_file = 0;
+
+// +--------------------------------------------------------------------+
+
+#ifdef _DEBUG
+#define CrtSetDebugField(a) _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
+#define CrtClrDebugField(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
+#endif
+
+static void heapdump()
+{
+ _HEAPINFO hinfo;
+ int heapstatus;
+ DWORD used = 0;
+ DWORD avail = 0;
+ char report[256];
+
+ hinfo._pentry = NULL;
+ while ((heapstatus = _heapwalk( &hinfo )) == _HEAPOK) {
+ sprintf_s(report, "%6s block at %Fp of size %4.4X\n",
+ ( hinfo._useflag == _USEDENTRY ? "USED" : "FREE" ),
+ hinfo._pentry, hinfo._size);
+
+ _RPT0(_CRT_WARN, report);
+
+ if (hinfo._useflag == _USEDENTRY)
+ used += hinfo._size;
+ else
+ avail += hinfo._size;
+ }
+
+ sprintf_s(report, "------\nUsed Blocks: %d\nAvail Blocks: %d\nTotal Blocks: %d\n", used, avail, used+avail); //-V576
+ _RPT0(_CRT_WARN, report);
+
+ switch (heapstatus) {
+ case _HEAPEMPTY:
+ _RPT0(_CRT_WARN, "OK - empty heap\n" );
+ break;
+ case _HEAPEND:
+ _RPT0(_CRT_WARN, "OK - end of heap\n" );
+ break;
+ case _HEAPBADPTR:
+ _RPT0(_CRT_WARN, "ERROR - bad pointer to heap\n" );
+ break;
+ case _HEAPBADBEGIN:
+ _RPT0(_CRT_WARN, "ERROR - bad start of heap\n" );
+ break;
+ case _HEAPBADNODE:
+ _RPT0(_CRT_WARN, "ERROR - bad node in heap\n" );
+ break;
+ }
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::OpenLog(const char* filename)
+{
+#ifdef _DEBUG
+ if (!filename || !strlen(filename))
+ filename = "memdbg.txt";
+
+ mem_log_file = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
+
+ if (mem_log_file) {
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_WARN, mem_log_file);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ERROR, mem_log_file);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ASSERT, mem_log_file);
+ }
+
+ _CrtMemCheckpoint(&mem_chk_p1);
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::CloseLog()
+{
+#ifdef _DEBUG
+ if (mem_log_file) {
+ CloseHandle(mem_log_file);
+ mem_log_file = 0;
+
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
+ }
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::Check()
+{
+#ifdef _DEBUG
+ if (! _CrtCheckMemory()) {
+ _RPT0(_CRT_ERROR, "\n\nMemory Check Failed.\n");
+ heapdump();
+ Checkpoint();
+ _asm { int 3 }
+ exit(1111);
+ }
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::Checkpoint()
+{
+#ifdef _DEBUG
+ if (mem_chk_level < PERIODIC) return;
+
+ _RPT0(_CRT_WARN, "\n\nMemory Checkpoint:\n"
+ "--------------------------------------------------\n");
+
+ _CrtMemState s;
+ _CrtMemCheckpoint(&mem_chk_p2);
+ _CrtMemDifference(&s, &mem_chk_p1, &mem_chk_p2);
+ _CrtMemDumpStatistics(&s);
+
+ memcpy(&mem_chk_p1, &mem_chk_p2, sizeof(mem_chk_p1));
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::Stats()
+{
+#ifdef _DEBUG
+ if (mem_chk_level < PERIODIC) return;
+
+ _RPT0(_CRT_WARN, "\n\nMemory Stats:\n"
+ "--------------------------------------------------\n");
+
+ _CrtMemState s;
+ _CrtMemCheckpoint(&s);
+ _CrtMemDumpStatistics(&s);
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::DumpLeaks()
+{
+#ifdef _DEBUG
+ _RPT0(_CRT_WARN, "\n\nMemory Dump Leaks:\n"
+ "--------------------------------------------------\n");
+ _CrtDumpMemoryLeaks();
+#endif
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Memory::SetLevel(LEVEL l)
+{
+#ifdef _DEBUG
+ mem_chk_level = l;
+
+ _CrtSetDbgFlag(0);
+
+ switch (mem_chk_level) {
+ case MAXIMAL: CrtSetDebugField(_CRTDBG_CHECK_ALWAYS_DF);
+ case PERIODIC: CrtSetDebugField(_CRTDBG_DELAY_FREE_MEM_DF);
+ case LEAKS: CrtSetDebugField(_CRTDBG_LEAK_CHECK_DF);
+ case OFF:
+ default: break;
+ }
+#endif
+}
+
diff --git a/FoundationEx/MemDebug.h b/FoundationEx/MemDebug.h
index fcfea5b..14bc0cf 100644
--- a/FoundationEx/MemDebug.h
+++ b/FoundationEx/MemDebug.h
@@ -1,91 +1,115 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: MemDebug.h
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Memory Debugging class
-*/
-
-
-#ifndef MemDebug_h
-#define MemDebug_h
-
-// +--------------------------------------------------------------------+
-
-#ifdef WIN32
-#include <windows.h>
-#include <windowsx.h>
-#endif
-
-#ifdef FOUNDATION_USE_MFC
-
-#ifndef _DEBUG
-
-inline void* __cdecl operator new(unsigned int s, const char*, int) { return ::operator new(s); }
-inline void __cdecl operator delete(void* p, const char*, int) { ::operator delete(p); }
-
-#else
-
-void* __cdecl operator new(unsigned int s, const char*, int);
-void __cdecl operator delete(void* p, const char*, int);
-
-#endif
-
-#else
-
-//
-// MEMORY DEBUGGING NOT SUPPORTED UNDER MFC
-//
-
-// +--------------------------------------------------------------------+
-
-class Memory
-{
-public:
- enum LEVEL { OFF, LEAKS, PERIODIC, MAXIMAL };
-
- static void OpenLog(const char* filename=0);
- static void CloseLog();
-
- static void Check();
- static void Checkpoint();
- static void Stats();
- static void DumpLeaks();
-
- static void SetLevel(LEVEL l);
-};
-
-// +--------------------------------------------------------------------+
-
-#ifndef _DEBUG
-
-inline void* __cdecl operator new(unsigned int s, const char*, int) { return ::operator new(s); }
-inline void __cdecl operator delete(void* p, const char*, int) { ::operator delete(p); }
-
-#else
-/*_CRTIMP*/
-void* __cdecl operator new(unsigned int, int, const char*, int);
-
-inline void* __cdecl operator new(unsigned int s, const char* f, int l)
- { return ::operator new(s, 1, f, l); }
-
-inline void* __cdecl operator new(unsigned int s)
- { return ::operator new(s, 1, __FILE__, __LINE__); }
-
-inline void __cdecl operator delete(void* p, const char*, int)
- { ::operator delete(p); }
-
-#endif _DEBUG
-
-// +--------------------------------------------------------------------+
-
-#endif FOUNDATION_USE_MFC
-
-#endif MemDebug_h
-
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: MemDebug.h
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Memory Debugging class
+*/
+
+
+#ifndef MemDebug_h
+#define MemDebug_h
+
+// +--------------------------------------------------------------------+
+
+#ifdef WIN32
+#include <windows.h>
+#include <windowsx.h>
+#endif
+
+#ifdef FOUNDATION_USE_MFC
+
+#ifndef _DEBUG
+
+inline void* __cdecl operator new(unsigned int s, const char*, int) { return ::operator new(s); }
+inline void __cdecl operator delete(void* p, const char*, int) { ::operator delete(p); }
+
+#else
+
+void* __cdecl operator new(unsigned int s, const char*, int);
+void __cdecl operator delete(void* p, const char*, int);
+
+#endif
+
+#else
+
+//
+// MEMORY DEBUGGING NOT SUPPORTED UNDER MFC
+//
+
+// +--------------------------------------------------------------------+
+
+class Memory
+{
+public:
+ enum LEVEL { OFF, LEAKS, PERIODIC, MAXIMAL };
+
+ static void OpenLog(const char* filename=0);
+ static void CloseLog();
+
+ static void Check();
+ static void Checkpoint();
+ static void Stats();
+ static void DumpLeaks();
+
+ static void SetLevel(LEVEL l);
+};
+
+// +--------------------------------------------------------------------+
+
+#ifndef _DEBUG
+
+inline void* __cdecl operator new(unsigned int s, const char*, int) { return ::operator new(s); }
+inline void __cdecl operator delete(void* p, const char*, int) { ::operator delete(p); }
+
+#else
+/*_CRTIMP*/
+void* __cdecl operator new(unsigned int, int, const char*, int);
+
+inline void* __cdecl operator new(unsigned int s, const char* f, int l)
+ { return ::operator new(s, 1, f, l); }
+
+inline void* __cdecl operator new(unsigned int s)
+ { return ::operator new(s, 1, __FILE__, __LINE__); }
+
+inline void __cdecl operator delete(void* p, const char*, int)
+ { ::operator delete(p); }
+
+#endif _DEBUG
+
+// +--------------------------------------------------------------------+
+
+#endif FOUNDATION_USE_MFC
+
+#endif MemDebug_h
+
diff --git a/FoundationEx/Text.cpp b/FoundationEx/Text.cpp
index 5f832ea..a845ca0 100644
--- a/FoundationEx/Text.cpp
+++ b/FoundationEx/Text.cpp
@@ -1,751 +1,775 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: text.cpp
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Implementation of the Text class
-*/
-
-#include "MemDebug.h"
-#include "Text.h"
-#include "stdio.h"
-#include <ctype.h>
-
-// +-------------------------------------------------------------------+
-// SPECIAL TEXT REP FOR NULL STRINGS
-// This is used only by the default constructor for the Text object,
-// to prevent extra rep allocation when constructing empty strings.
-
-TextRep TextRep::nullrep;
-
-TextRep::TextRep()
- : ref(1234567), data(0), length(0), hash(0), sensitive(true)
-{
-#ifdef MEM_DEBUG
- data = new(__FILE__,__LINE__) char[4];
-#else
- data = new char[4];
-#endif
-
- if (data)
- ZeroMemory(data, 4);
-}
-
-// +-------------------------------------------------------------------+
-
-ThreadSync TextRep::sync;
-
-
-TextRep::TextRep(const char* s)
- : ref(1), length(0), sensitive(true)
-{
- if (s) length = ::strlen(s);
-
-#ifdef MEM_DEBUG
- data = new(__FILE__,__LINE__) char[length+1];
-#else
- data = new char[length+1];
-#endif
-
- if (data) {
- if (s) ::strcpy(data, s);
- else data[length] = '\0';
-
- dohash();
- }
-}
-
-TextRep::TextRep(const char* s, int len)
- : ref(1), length(len), sensitive(true)
-{
- if (length < 0) length = 0;
-
-#ifdef MEM_DEBUG
- data = new(__FILE__,__LINE__) char[length+1];
-#else
- data = new char[length+1];
-#endif
-
- if (data) {
- ::CopyMemory(data, s, length);
- data[length] = '\0';
- dohash();
- }
-}
-
-TextRep::TextRep(char c, int len)
- : ref(1), length(len), sensitive(true)
-{
- if (length < 0) length = 0;
-
-#ifdef MEM_DEBUG
- data = new(__FILE__,__LINE__) char[length+1];
-#else
- data = new char[length+1];
-#endif
-
- if (data) {
- ::FillMemory(data, length, c);
- data[length] = '\0';
- dohash();
- }
-}
-
-TextRep::TextRep(const TextRep* rep)
- : ref(1)
-{
- length = rep->length;
-
-#ifdef MEM_DEBUG
- data = new(__FILE__,__LINE__) char[length+1];
-#else
- data = new char[length+1];
-#endif
-
- hash = rep->hash;
- sensitive = rep->sensitive;
-
- if (data)
- ::strcpy(data, rep->data);
-}
-
-TextRep::~TextRep()
-{
- delete[] data;
-}
-
-void
-TextRep::addref()
-{
- sync.acquire();
- ref++;
- sync.release();
-}
-
-long
-TextRep::deref()
-{
- sync.acquire();
- long r = --ref;
- sync.release();
- return r;
-}
-
-inline static void mash(unsigned& hash, unsigned chars)
-{
- hash = (chars ^ ((hash << 5) | (hash >> (8*sizeof(unsigned) - 5))));
-}
-
-void
-TextRep::dohash()
-{
- unsigned hv = (unsigned)length; // Mix in the string length.
- unsigned i = length*sizeof(char)/sizeof(unsigned);
- const unsigned* p = (const unsigned*)data;
-
- while (i--)
- mash(hv, *p++); // XOR in the characters.
-
- // XOR in any remaining characters:
- i = length*sizeof(char)%sizeof(unsigned);
- if (i) {
- unsigned h = 0;
- const char* c = (const char*)p;
- while (i--)
- h = ((h << 8*sizeof(char)) | *c++);
- mash(hv, h);
- }
-
- hash = hv;
-}
-
-// +-------------------------------------------------------------------+
-
-Text::Text()
-{
- rep = &TextRep::nullrep;
- rep->addref();
- sym = rep->data;
-}
-
-Text::Text(char c)
-{
- char buf[2]; buf[0] = c; buf[1] = '\0';
-
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(buf);
-#else
- rep = new TextRep(buf);
-#endif
-
- if (!rep) {
- rep = &TextRep::nullrep;
- rep->addref();
- }
-
- sym = rep->data;
-}
-
-Text::Text(const char* s)
-{
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(s);
-#else
- rep = new TextRep(s);
-#endif
-
- if (!rep) {
- rep = &TextRep::nullrep;
- rep->addref();
- }
-
- sym = rep->data;
-}
-
-Text::Text(const char* s, int len)
-{
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(s, len);
-#else
- rep = new TextRep(s, len);
-#endif
-
- if (!rep) {
- rep = &TextRep::nullrep;
- rep->addref();
- }
-
- sym = rep->data;
-}
-
-Text::Text(char c, int len)
-{
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(c, len);
-#else
- rep = new TextRep(c, len);
-#endif
-
- if (!rep) {
- rep = &TextRep::nullrep;
- rep->addref();
- }
-
- sym = rep->data;
-}
-
-Text::Text(const Text& s)
-{
- rep = s.rep;
- rep->addref();
- sym = rep->data;
-}
-
-Text::~Text()
-{
- if (rep->deref() == 0) delete rep;
-
- rep = &TextRep::nullrep;
- sym = rep->data;
-}
-
-Text&
-Text::operator=(const char* s)
-{
- if (rep->deref() == 0) delete rep;
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(s);
-#else
- rep = new TextRep(s);
-#endif
-
- if (!rep)
- rep = &TextRep::nullrep;
- sym = rep->data;
- return *this;
-}
-
-Text&
-Text::operator=(const Text& s)
-{
- s.rep->addref();
- if (rep->deref() == 0) delete rep;
- rep = s.rep;
- sym = rep->data;
- return *this;
-}
-
-Text
-Text::operator+(char c)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[rep->length + 2];
-#else
- char* buf = new char[rep->length + 2];
-#endif
-
- if (buf) {
- ::strcpy(buf, sym);
- buf[rep->length] = c;
- buf[rep->length+1] = '\0';
- Text retval(buf);
- delete [] buf;
- return retval;
- }
-
- else {
- return *this;
- }
-}
-
-Text
-Text::operator+(const char* s)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[::strlen(s) + rep->length + 1];
-#else
- char* buf = new char[::strlen(s) + rep->length + 1];
-#endif
-
- if (buf) {
- ::strcpy(buf, sym);
- ::strcat(buf, s);
- Text retval(buf);
- delete [] buf;
- return retval;
- }
-
- else {
- return *this;
- }
-}
-
-Text
-Text::operator+(const Text& s)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[s.rep->length + rep->length + 1];
-#else
- char* buf = new char[s.rep->length + rep->length + 1];
-#endif
-
- if (buf) {
- ::strcpy(buf, sym);
- ::strcat(buf, s.sym);
- Text retval(buf);
- delete [] buf;
- return retval;
- }
-
- else {
- return *this;
- }
-}
-
-bool
-Text::isSensitive() const
-{
- return rep->sensitive;
-}
-
-void
-Text::setSensitive(bool s)
-{
- rep->sensitive = s;
-}
-
-Text&
-Text::append(char c)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[rep->length + 2];
-#else
- char* buf = new char[rep->length + 2];
-#endif
-
- if (buf) {
- ::strcpy(buf, sym);
- buf[rep->length] = c;
- buf[rep->length+1] = '\0';
- if (rep->deref() == 0) delete rep;
-
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(buf);
-#else
- rep = new TextRep(buf);
-#endif
-
- if (!rep)
- rep = &TextRep::nullrep;
-
- sym = rep->data;
- delete [] buf;
- }
-
- return *this;
-}
-
-Text&
-Text::append(const char* s)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[::strlen(s) + rep->length + 1];
-#else
- char* buf = new char[::strlen(s) + rep->length + 1];
-#endif
-
- if (buf) {
- ::strcpy(buf, sym);
- ::strcat(buf, s);
- if (rep->deref() == 0) delete rep;
-
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(buf);
-#else
- rep = new TextRep(buf);
-#endif
-
- if (!rep)
- rep = &TextRep::nullrep;
-
- sym = rep->data;
- delete [] buf;
- }
-
- return *this;
-}
-
-Text&
-Text::append(const Text& s)
-{
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[s.rep->length + rep->length + 1];
-#else
- char* buf = new char[s.rep->length + rep->length + 1];
-#endif
-
- if (buf) {
- int lenA = rep->length;
- int lenB = s.rep->length;
-
- CopyMemory(buf, sym, lenA);
- CopyMemory(buf + lenA, s.sym, lenB);
- buf[lenA + lenB] = 0;
-
- if (rep->deref() == 0) delete rep;
-
-#ifdef MEM_DEBUG
- rep = new(__FILE__,__LINE__) TextRep(buf, lenA + lenB);
-#else
- rep = new TextRep(buf);
-#endif
-
- if (!rep)
- rep = &TextRep::nullrep;
-
- sym = rep->data;
- delete [] buf;
- }
-
- return *this;
-}
-
-void
-Text::clone()
-{
- if (rep->ref > 1) {
- rep->deref();
-
-#ifdef MEM_DEBUG
- TextRep* t = new(__FILE__,__LINE__) TextRep(rep);
-#else
- TextRep* t = new TextRep(rep);
-#endif
-
- rep = t;
-
- if (!rep)
- rep = &TextRep::nullrep;
-
- sym = rep->data;
- }
-}
-
-char
-Text::operator[](int index) const
-{
- if (index < (int) rep->length)
- return sym[index];
- else
- throw "BOUNDS ERROR";
-
- return '\0';
-}
-
-char
-Text::operator()(int index) const
-{
- return sym[index];
-}
-
-char&
-Text::operator[](int index)
-{
- if (index < (int) rep->length) {
- clone();
- return (char&) sym[index];
- }
- else
- throw "BOUNDS ERROR";
-
- return (char&) sym[0];
-}
-
-char&
-Text::operator()(int index)
-{
- clone();
- return (char&) sym[index];
-}
-
-Text
-Text::operator()(int start, int len) const
-{
- if (start > rep->length || len <= 0)
- return Text();
-
- if (start + len > rep->length)
- len = rep->length - start;
-
-#ifdef MEM_DEBUG
- char* buf = new(__FILE__,__LINE__) char[len+1];
-#else
- char* buf = new char[len+1];
-#endif
-
- if (buf) {
- ::strncpy(buf, sym+start, len);
- buf[len] = '\0';
-
- Text retval(buf);
- delete [] buf;
- return retval;
- }
-
- return Text();
-}
-
-bool
-Text::contains(char c) const
-{
- if (rep->length > 0) {
- if (!rep->sensitive) {
- char alt = c;
- if (islower(alt)) alt = toupper(alt);
- else if (isupper(alt)) alt = tolower(alt);
-
- if (strchr(rep->data, alt) != 0)
- return true;
- }
-
- if (strchr(rep->data, c) != 0)
- return true;
- }
-
- return false;
-}
-
-bool
-Text::contains(const char* pattern) const
-{
- if (rep->length > 0 && pattern && *pattern) {
- if (rep->sensitive) {
- if (strstr(rep->data, pattern) != 0)
- return true;
- }
- else {
- Text smash1(*this);
- smash1.toLower();
- Text smash2(pattern);
- smash2.toLower();
-
- if (strstr(smash1.data(), smash2.data()) != 0)
- return true;
- }
- }
-
- return false;
-}
-
-bool
-Text::containsAnyOf(const char* charSet) const
-{
- if (rep->length > 0 && charSet && *charSet) {
- if (rep->sensitive) {
- if (strpbrk(rep->data, charSet) != 0)
- return true;
- }
- else {
- Text smash1(*this);
- smash1.toLower();
- Text smash2(charSet);
- smash2.toLower();
-
- if (strpbrk(smash1.data(), smash2.data()) != 0)
- return true;
- }
- }
-
- return false;
-}
-
-int
-Text::indexOf(char c) const
-{
- if (rep->length > 0) {
- if (!rep->sensitive) {
- char alt = c;
- if (islower(alt)) alt = toupper(alt);
- else if (isupper(alt)) alt = tolower(alt);
-
- const char* p = strchr(rep->data, alt);
-
- if (p)
- return (p - rep->data);
- }
-
- const char* p = strchr(rep->data, c);
-
- if (p)
- return (p - rep->data);
- }
-
- return -1;
-}
-
-int
-Text::indexOf(const char* pattern) const
-{
- if (rep->length > 0 && pattern && *pattern) {
- if (rep->sensitive) {
- const char* p = strstr(rep->data, pattern);
- if (p) return (p - rep->data);
- }
- else {
- Text smash1(*this);
- smash1.toLower();
- Text smash2(pattern);
- smash2.toLower();
-
- const char* p = strstr(smash1.data(), smash2.data());
- if (p) return (p - smash1.data());
- }
- }
-
- return -1;
-}
-
-void
-Text::toLower()
-{
- clone();
- size_t n = rep->length;
- char* p = (char*) sym;
- while (n--) {
- *p = tolower((unsigned char)*p);
- p++;
- }
-
- rep->dohash();
-}
-
-void
-Text::toUpper()
-{
- clone();
- size_t n = rep->length;
- char* p = (char*) sym;
- while ( n-- ) {
- *p = toupper((unsigned char)*p);
- p++;
- }
-
- rep->dohash();
-}
-
-Text
-Text::substring(int start, int length)
-{
- Text result;
-
- if (start >= 0 && start < (int) rep->length && length > 0) {
- if (start + length > (int) rep->length)
- length = (int) rep->length - start;
-
- const char* s = sym + start;
-
-#ifdef MEM_DEBUG
- result.rep = new(__FILE__,__LINE__) TextRep(s, length);
-#else
- result.rep = new TextRep(s, length);
-#endif
-
- if (!result.rep)
- result.rep = &TextRep::nullrep;
-
- result.sym = result.rep->data;
- }
-
- return result;
-}
-
-Text
-Text::trim()
-{
- Text result;
-
- if (rep->length) {
- const char* p = sym;
- const char* q = sym + rep->length-1;
-
- while (p && *p && isspace(*p)) p++;
- while (q>p && *q && isspace(*q)) q--;
-
- result = substring(p-sym, q-p+1);
- }
-
- return result;
-}
-
-Text
-Text::replace(const char* pattern, const char* substitution)
-{
- Text result;
-
- if (rep->length && pattern && *pattern) {
- int index = 0;
- int skip = strlen(pattern);
- do {
- const char* p = strstr(rep->data + index, pattern);
- if (p) {
- int len = (p - rep->data + index);
- result.append(substring(index, len));
- result.append(substitution);
- index += len + skip;
- }
- else if (index < rep->length) {
- result.append(substring(index, rep->length-index));
- index = -1;
- }
- }
- while (index >= 0 && index < rep->length);
- }
-
- return result;
-}
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: text.cpp
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Implementation of the Text class
+*/
+
+#include "MemDebug.h"
+#include "Text.h"
+#include "stdio.h"
+#include <ctype.h>
+
+// +-------------------------------------------------------------------+
+// SPECIAL TEXT REP FOR NULL STRINGS
+// This is used only by the default constructor for the Text object,
+// to prevent extra rep allocation when constructing empty strings.
+
+TextRep TextRep::nullrep;
+
+TextRep::TextRep()
+ : ref(1234567), data(0), length(0), hash(0), sensitive(true)
+{
+#ifdef MEM_DEBUG
+ data = new(__FILE__,__LINE__) char[4];
+#else
+ data = new char[4];
+#endif
+
+ if (data)
+ ZeroMemory(data, 4);
+}
+
+// +-------------------------------------------------------------------+
+
+ThreadSync TextRep::sync;
+
+
+TextRep::TextRep(const char* s)
+ : ref(1), length(0), sensitive(true)
+{
+ if (s) length = ::strlen(s);
+
+#ifdef MEM_DEBUG
+ data = new(__FILE__,__LINE__) char[length+1];
+#else
+ data = new char[length+1];
+#endif
+
+ if (data) {
+ if (s) ::strcpy(data, s);
+ else data[length] = '\0';
+
+ dohash();
+ }
+}
+
+TextRep::TextRep(const char* s, int len)
+ : ref(1), length(len), sensitive(true)
+{
+ if (length < 0) length = 0;
+
+#ifdef MEM_DEBUG
+ data = new(__FILE__,__LINE__) char[length+1];
+#else
+ data = new char[length+1];
+#endif
+
+ if (data) {
+ ::CopyMemory(data, s, length);
+ data[length] = '\0';
+ dohash();
+ }
+}
+
+TextRep::TextRep(char c, int len)
+ : ref(1), length(len), sensitive(true)
+{
+ if (length < 0) length = 0;
+
+#ifdef MEM_DEBUG
+ data = new(__FILE__,__LINE__) char[length+1];
+#else
+ data = new char[length+1];
+#endif
+
+ if (data) {
+ ::FillMemory(data, length, c);
+ data[length] = '\0';
+ dohash();
+ }
+}
+
+TextRep::TextRep(const TextRep* rep)
+ : ref(1)
+{
+ length = rep->length;
+
+#ifdef MEM_DEBUG
+ data = new(__FILE__,__LINE__) char[length+1];
+#else
+ data = new char[length+1];
+#endif
+
+ hash = rep->hash;
+ sensitive = rep->sensitive;
+
+ if (data)
+ ::strcpy(data, rep->data);
+}
+
+TextRep::~TextRep()
+{
+ delete[] data;
+}
+
+void
+TextRep::addref()
+{
+ sync.acquire();
+ ref++;
+ sync.release();
+}
+
+long
+TextRep::deref()
+{
+ sync.acquire();
+ long r = --ref;
+ sync.release();
+ return r;
+}
+
+inline static void mash(unsigned& hash, unsigned chars)
+{
+ hash = (chars ^ ((hash << 5) | (hash >> (8*sizeof(unsigned) - 5))));
+}
+
+void
+TextRep::dohash()
+{
+ unsigned hv = (unsigned)length; // Mix in the string length.
+ unsigned i = length*sizeof(char)/sizeof(unsigned);
+ const unsigned* p = (const unsigned*)data;
+
+ while (i--)
+ mash(hv, *p++); // XOR in the characters.
+
+ // XOR in any remaining characters:
+ i = length*sizeof(char)%sizeof(unsigned);
+ if (i) {
+ unsigned h = 0;
+ const char* c = (const char*)p;
+ while (i--)
+ h = ((h << 8*sizeof(char)) | *c++);
+ mash(hv, h);
+ }
+
+ hash = hv;
+}
+
+// +-------------------------------------------------------------------+
+
+Text::Text()
+{
+ rep = &TextRep::nullrep;
+ rep->addref();
+ sym = rep->data;
+}
+
+Text::Text(char c)
+{
+ char buf[2]; buf[0] = c; buf[1] = '\0';
+
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(buf);
+#else
+ rep = new TextRep(buf);
+#endif
+
+ if (!rep) {
+ rep = &TextRep::nullrep;
+ rep->addref();
+ }
+
+ sym = rep->data;
+}
+
+Text::Text(const char* s)
+{
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(s);
+#else
+ rep = new TextRep(s);
+#endif
+
+ if (!rep) {
+ rep = &TextRep::nullrep;
+ rep->addref();
+ }
+
+ sym = rep->data;
+}
+
+Text::Text(const char* s, int len)
+{
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(s, len);
+#else
+ rep = new TextRep(s, len);
+#endif
+
+ if (!rep) {
+ rep = &TextRep::nullrep;
+ rep->addref();
+ }
+
+ sym = rep->data;
+}
+
+Text::Text(char c, int len)
+{
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(c, len);
+#else
+ rep = new TextRep(c, len);
+#endif
+
+ if (!rep) {
+ rep = &TextRep::nullrep;
+ rep->addref();
+ }
+
+ sym = rep->data;
+}
+
+Text::Text(const Text& s)
+{
+ rep = s.rep;
+ rep->addref();
+ sym = rep->data;
+}
+
+Text::~Text()
+{
+ if (rep->deref() == 0) delete rep;
+
+ rep = &TextRep::nullrep;
+ sym = rep->data;
+}
+
+Text&
+Text::operator=(const char* s)
+{
+ if (rep->deref() == 0) delete rep;
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(s);
+#else
+ rep = new TextRep(s);
+#endif
+
+ if (!rep)
+ rep = &TextRep::nullrep;
+ sym = rep->data;
+ return *this;
+}
+
+Text&
+Text::operator=(const Text& s)
+{
+ s.rep->addref();
+ if (rep->deref() == 0) delete rep;
+ rep = s.rep;
+ sym = rep->data;
+ return *this;
+}
+
+Text
+Text::operator+(char c)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[rep->length + 2];
+#else
+ char* buf = new char[rep->length + 2];
+#endif
+
+ if (buf) {
+ ::strcpy(buf, sym);
+ buf[rep->length] = c;
+ buf[rep->length+1] = '\0';
+ Text retval(buf);
+ delete [] buf;
+ return retval;
+ }
+
+ else {
+ return *this;
+ }
+}
+
+Text
+Text::operator+(const char* s)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[::strlen(s) + rep->length + 1];
+#else
+ char* buf = new char[::strlen(s) + rep->length + 1];
+#endif
+
+ if (buf) {
+ ::strcpy(buf, sym);
+ ::strcat(buf, s);
+ Text retval(buf);
+ delete [] buf;
+ return retval;
+ }
+
+ else {
+ return *this;
+ }
+}
+
+Text
+Text::operator+(const Text& s)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[s.rep->length + rep->length + 1];
+#else
+ char* buf = new char[s.rep->length + rep->length + 1];
+#endif
+
+ if (buf) {
+ ::strcpy(buf, sym);
+ ::strcat(buf, s.sym);
+ Text retval(buf);
+ delete [] buf;
+ return retval;
+ }
+
+ else {
+ return *this;
+ }
+}
+
+bool
+Text::isSensitive() const
+{
+ return rep->sensitive;
+}
+
+void
+Text::setSensitive(bool s)
+{
+ rep->sensitive = s;
+}
+
+Text&
+Text::append(char c)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[rep->length + 2];
+#else
+ char* buf = new char[rep->length + 2];
+#endif
+
+ if (buf) {
+ ::strcpy(buf, sym);
+ buf[rep->length] = c;
+ buf[rep->length+1] = '\0';
+ if (rep->deref() == 0) delete rep;
+
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(buf);
+#else
+ rep = new TextRep(buf);
+#endif
+
+ if (!rep)
+ rep = &TextRep::nullrep;
+
+ sym = rep->data;
+ delete [] buf;
+ }
+
+ return *this;
+}
+
+Text&
+Text::append(const char* s)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[::strlen(s) + rep->length + 1];
+#else
+ char* buf = new char[::strlen(s) + rep->length + 1];
+#endif
+
+ if (buf) {
+ ::strcpy(buf, sym);
+ ::strcat(buf, s);
+ if (rep->deref() == 0) delete rep;
+
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(buf);
+#else
+ rep = new TextRep(buf);
+#endif
+
+ if (!rep)
+ rep = &TextRep::nullrep;
+
+ sym = rep->data;
+ delete [] buf;
+ }
+
+ return *this;
+}
+
+Text&
+Text::append(const Text& s)
+{
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[s.rep->length + rep->length + 1];
+#else
+ char* buf = new char[s.rep->length + rep->length + 1];
+#endif
+
+ if (buf) {
+ int lenA = rep->length;
+ int lenB = s.rep->length;
+
+ CopyMemory(buf, sym, lenA);
+ CopyMemory(buf + lenA, s.sym, lenB);
+ buf[lenA + lenB] = 0;
+
+ if (rep->deref() == 0) delete rep;
+
+#ifdef MEM_DEBUG
+ rep = new(__FILE__,__LINE__) TextRep(buf, lenA + lenB);
+#else
+ rep = new TextRep(buf);
+#endif
+
+ if (!rep)
+ rep = &TextRep::nullrep;
+
+ sym = rep->data;
+ delete [] buf;
+ }
+
+ return *this;
+}
+
+void
+Text::clone()
+{
+ if (rep->ref > 1) {
+ rep->deref();
+
+#ifdef MEM_DEBUG
+ TextRep* t = new(__FILE__,__LINE__) TextRep(rep);
+#else
+ TextRep* t = new TextRep(rep);
+#endif
+
+ rep = t;
+
+ if (!rep)
+ rep = &TextRep::nullrep;
+
+ sym = rep->data;
+ }
+}
+
+char
+Text::operator[](int index) const
+{
+ if (index < (int) rep->length)
+ return sym[index];
+ else
+ throw "BOUNDS ERROR";
+
+ return '\0';
+}
+
+char
+Text::operator()(int index) const
+{
+ return sym[index];
+}
+
+char&
+Text::operator[](int index)
+{
+ if (index < (int) rep->length) {
+ clone();
+ return (char&) sym[index];
+ }
+ else
+ throw "BOUNDS ERROR";
+
+ return (char&) sym[0];
+}
+
+char&
+Text::operator()(int index)
+{
+ clone();
+ return (char&) sym[index];
+}
+
+Text
+Text::operator()(int start, int len) const
+{
+ if (start > rep->length || len <= 0)
+ return Text();
+
+ if (start + len > rep->length)
+ len = rep->length - start;
+
+#ifdef MEM_DEBUG
+ char* buf = new(__FILE__,__LINE__) char[len+1];
+#else
+ char* buf = new char[len+1];
+#endif
+
+ if (buf) {
+ ::strncpy(buf, sym+start, len);
+ buf[len] = '\0';
+
+ Text retval(buf);
+ delete [] buf;
+ return retval;
+ }
+
+ return Text();
+}
+
+bool
+Text::contains(char c) const
+{
+ if (rep->length > 0) {
+ if (!rep->sensitive) {
+ char alt = c;
+ if (islower(alt)) alt = toupper(alt);
+ else if (isupper(alt)) alt = tolower(alt);
+
+ if (strchr(rep->data, alt) != 0)
+ return true;
+ }
+
+ if (strchr(rep->data, c) != 0)
+ return true;
+ }
+
+ return false;
+}
+
+bool
+Text::contains(const char* pattern) const
+{
+ if (rep->length > 0 && pattern && *pattern) {
+ if (rep->sensitive) {
+ if (strstr(rep->data, pattern) != 0)
+ return true;
+ }
+ else {
+ Text smash1(*this);
+ smash1.toLower();
+ Text smash2(pattern);
+ smash2.toLower();
+
+ if (strstr(smash1.data(), smash2.data()) != 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+Text::containsAnyOf(const char* charSet) const
+{
+ if (rep->length > 0 && charSet && *charSet) {
+ if (rep->sensitive) {
+ if (strpbrk(rep->data, charSet) != 0)
+ return true;
+ }
+ else {
+ Text smash1(*this);
+ smash1.toLower();
+ Text smash2(charSet);
+ smash2.toLower();
+
+ if (strpbrk(smash1.data(), smash2.data()) != 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int
+Text::indexOf(char c) const
+{
+ if (rep->length > 0) {
+ if (!rep->sensitive) {
+ char alt = c;
+ if (islower(alt)) alt = toupper(alt);
+ else if (isupper(alt)) alt = tolower(alt);
+
+ const char* p = strchr(rep->data, alt);
+
+ if (p)
+ return (p - rep->data);
+ }
+
+ const char* p = strchr(rep->data, c);
+
+ if (p)
+ return (p - rep->data);
+ }
+
+ return -1;
+}
+
+int
+Text::indexOf(const char* pattern) const
+{
+ if (rep->length > 0 && pattern && *pattern) {
+ if (rep->sensitive) {
+ const char* p = strstr(rep->data, pattern);
+ if (p) return (p - rep->data);
+ }
+ else {
+ Text smash1(*this);
+ smash1.toLower();
+ Text smash2(pattern);
+ smash2.toLower();
+
+ const char* p = strstr(smash1.data(), smash2.data());
+ if (p) return (p - smash1.data());
+ }
+ }
+
+ return -1;
+}
+
+void
+Text::toLower()
+{
+ clone();
+ size_t n = rep->length;
+ char* p = (char*) sym;
+ while (n--) {
+ *p = tolower((unsigned char)*p);
+ p++;
+ }
+
+ rep->dohash();
+}
+
+void
+Text::toUpper()
+{
+ clone();
+ size_t n = rep->length;
+ char* p = (char*) sym;
+ while ( n-- ) {
+ *p = toupper((unsigned char)*p);
+ p++;
+ }
+
+ rep->dohash();
+}
+
+Text
+Text::substring(int start, int length)
+{
+ Text result;
+
+ if (start >= 0 && start < (int) rep->length && length > 0) {
+ if (start + length > (int) rep->length)
+ length = (int) rep->length - start;
+
+ const char* s = sym + start;
+
+#ifdef MEM_DEBUG
+ result.rep = new(__FILE__,__LINE__) TextRep(s, length);
+#else
+ result.rep = new TextRep(s, length);
+#endif
+
+ if (!result.rep)
+ result.rep = &TextRep::nullrep;
+
+ result.sym = result.rep->data;
+ }
+
+ return result;
+}
+
+Text
+Text::trim()
+{
+ Text result;
+
+ if (rep->length) {
+ const char* p = sym;
+ const char* q = sym + rep->length-1;
+
+ while (p && *p && isspace(*p)) p++;
+ while (q>p && *q && isspace(*q)) q--;
+
+ result = substring(p-sym, q-p+1);
+ }
+
+ return result;
+}
+
+Text
+Text::replace(const char* pattern, const char* substitution)
+{
+ Text result;
+
+ if (rep->length && pattern && *pattern) {
+ int index = 0;
+ int skip = strlen(pattern);
+ do {
+ const char* p = strstr(rep->data + index, pattern);
+ if (p) {
+ int len = (p - rep->data + index);
+ result.append(substring(index, len));
+ result.append(substitution);
+ index += len + skip;
+ }
+ else if (index < rep->length) {
+ result.append(substring(index, rep->length-index));
+ index = -1;
+ }
+ }
+ while (index >= 0 && index < rep->length);
+ }
+
+ return result;
+}
diff --git a/FoundationEx/Text.h b/FoundationEx/Text.h
index 3abacc3..ee946f8 100644
--- a/FoundationEx/Text.h
+++ b/FoundationEx/Text.h
@@ -1,193 +1,217 @@
-/* Project FoundationEx
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: FoundationEx
- FILE: Text.h
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Declaration of the Text class
-*/
-
-#ifndef Text_h
-#define Text_h
-
-#include <string.h>
-#include <windows.h>
-#include "ThreadSync.h"
-
-// +-------------------------------------------------------------------+
-
-class TextRep
-{
- friend class Text;
-
-public:
- TextRep();
- ~TextRep();
-
-private:
- TextRep(const char* s);
- TextRep(const char* s, int len);
- TextRep(char c, int len);
- TextRep(const TextRep* rep);
-
- void addref();
- long deref();
-
- void dohash();
-
- char* data;
- long ref;
- int length;
- unsigned hash;
- bool sensitive;
-
- static ThreadSync sync;
- static TextRep nullrep;
-};
-
-// +-------------------------------------------------------------------+
-
-class Text
-{
-public:
- static const char* TYPENAME() { return "Text"; }
-
- Text();
- Text(char c);
- Text(const char* s);
- Text(const char* s, int len);
- Text(char c, int len);
- Text(const Text& s);
- ~Text();
-
- // case sensitivity
- bool isSensitive() const;
- void setSensitive(bool s);
-
- // comparison
- int compare(const char* s) const;
- int compare(const Text& s) const;
-
- // assignment
- Text& operator=(const char* s);
- Text& operator=(const Text& s);
-
- // catenation
- Text& append(char c);
- Text& append(const char* s);
- Text& append(const Text& s);
-
- Text operator+(char c);
- Text operator+(const char* s);
- Text operator+(const Text& s);
-
- Text& operator+=(char c) { return append(c); }
- Text& operator+=(const char* s) { return append(s); }
- Text& operator+=(const Text& s) { return append(s); }
-
- // indexing
- char operator[](int index) const;
- char operator()(int index) const;
- char& operator[](int index);
- char& operator()(int index);
-
- Text operator()(int start, int len) const;
-
- // access
- int length() const { return rep->length; }
- unsigned hash() const { return rep->hash; }
-
- const char* data() const { return sym; }
- operator const char* () const { return sym; }
-
- bool contains(char c) const;
- bool contains(const char* s) const;
-
- bool containsAnyOf(const char* charSet) const;
-
- int indexOf(char c) const;
- int indexOf(const char* s) const;
-
- // mutation
- void toLower();
- void toUpper();
-
- // substring
- Text substring(int start, int length);
- Text trim();
- Text replace(const char* pattern, const char* substitution);
-
-private:
- void clone();
-
- const char* sym;
- TextRep* rep;
-};
-
-// +-------------------------------------------------------------------+
-
-inline int Text::compare(const char* s) const
-{
- if (rep->sensitive)
- return strcmp(sym, s);
- else
- return _stricmp(sym, s);
-}
-
-inline int Text::compare(const Text& s) const
-{
- if (rep->sensitive && s.rep->sensitive)
- return strcmp(sym, s.sym);
- else
- return _stricmp(sym, s.sym);
-}
-
-// +-------------------------------------------------------------------+
-
-inline int operator==(const Text& l, const Text& r) {
- return (l.length() == r.length()) && (l.compare(r) == 0); }
-inline int operator!=(const Text& l, const Text& r) { return l.compare(r) != 0; }
-inline int operator< (const Text& l, const Text& r) { return l.compare(r) < 0; }
-inline int operator<=(const Text& l, const Text& r) { return l.compare(r) <= 0; }
-inline int operator> (const Text& l, const Text& r) { return l.compare(r) > 0; }
-inline int operator>=(const Text& l, const Text& r) { return l.compare(r) >= 0; }
-
-inline int operator==(const char* l, const Text& r) { return r.compare(l) == 0; }
-inline int operator!=(const char* l, const Text& r) { return r.compare(l) != 0; }
-inline int operator< (const char* l, const Text& r) { return r.compare(l) < 0; }
-inline int operator<=(const char* l, const Text& r) { return r.compare(l) <= 0; }
-inline int operator> (const char* l, const Text& r) { return r.compare(l) > 0; }
-inline int operator>=(const char* l, const Text& r) { return r.compare(l) >= 0; }
-
-inline int operator==( char* l, const Text& r) { return r.compare(l) == 0; }
-inline int operator!=( char* l, const Text& r) { return r.compare(l) != 0; }
-inline int operator< ( char* l, const Text& r) { return r.compare(l) < 0; }
-inline int operator<=( char* l, const Text& r) { return r.compare(l) <= 0; }
-inline int operator> ( char* l, const Text& r) { return r.compare(l) > 0; }
-inline int operator>=( char* l, const Text& r) { return r.compare(l) >= 0; }
-
-inline int operator==(const Text& l, const char* r) { return l.compare(r) == 0; }
-inline int operator!=(const Text& l, const char* r) { return l.compare(r) != 0; }
-inline int operator< (const Text& l, const char* r) { return l.compare(r) < 0; }
-inline int operator<=(const Text& l, const char* r) { return l.compare(r) <= 0; }
-inline int operator> (const Text& l, const char* r) { return l.compare(r) > 0; }
-inline int operator>=(const Text& l, const char* r) { return l.compare(r) >= 0; }
-
-inline int operator==(const Text& l, char* r) { return l.compare(r) == 0; }
-inline int operator!=(const Text& l, char* r) { return l.compare(r) != 0; }
-inline int operator< (const Text& l, char* r) { return l.compare(r) < 0; }
-inline int operator<=(const Text& l, char* r) { return l.compare(r) <= 0; }
-inline int operator> (const Text& l, char* r) { return l.compare(r) > 0; }
-inline int operator>=(const Text& l, char* r) { return l.compare(r) >= 0; }
-
-inline Text operator+(const char* l, const Text& r) { return Text(l) + r; }
-inline Text operator+( char* l, const Text& r) { return Text(l) + r; }
-
-// +-------------------------------------------------------------------+
-
-#endif Text_h
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: FoundationEx
+ FILE: Text.h
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Declaration of the Text class
+*/
+
+#ifndef Text_h
+#define Text_h
+
+#include <string.h>
+#include <windows.h>
+#include "ThreadSync.h"
+
+// +-------------------------------------------------------------------+
+
+class TextRep
+{
+ friend class Text;
+
+public:
+ TextRep();
+ ~TextRep();
+
+private:
+ TextRep(const char* s);
+ TextRep(const char* s, int len);
+ TextRep(char c, int len);
+ TextRep(const TextRep* rep);
+
+ void addref();
+ long deref();
+
+ void dohash();
+
+ char* data;
+ long ref;
+ int length;
+ unsigned hash;
+ bool sensitive;
+
+ static ThreadSync sync;
+ static TextRep nullrep;
+};
+
+// +-------------------------------------------------------------------+
+
+class Text
+{
+public:
+ static const char* TYPENAME() { return "Text"; }
+
+ Text();
+ Text(char c);
+ Text(const char* s);
+ Text(const char* s, int len);
+ Text(char c, int len);
+ Text(const Text& s);
+ ~Text();
+
+ // case sensitivity
+ bool isSensitive() const;
+ void setSensitive(bool s);
+
+ // comparison
+ int compare(const char* s) const;
+ int compare(const Text& s) const;
+
+ // assignment
+ Text& operator=(const char* s);
+ Text& operator=(const Text& s);
+
+ // catenation
+ Text& append(char c);
+ Text& append(const char* s);
+ Text& append(const Text& s);
+
+ Text operator+(char c);
+ Text operator+(const char* s);
+ Text operator+(const Text& s);
+
+ Text& operator+=(char c) { return append(c); }
+ Text& operator+=(const char* s) { return append(s); }
+ Text& operator+=(const Text& s) { return append(s); }
+
+ // indexing
+ char operator[](int index) const;
+ char operator()(int index) const;
+ char& operator[](int index);
+ char& operator()(int index);
+
+ Text operator()(int start, int len) const;
+
+ // access
+ int length() const { return rep->length; }
+ unsigned hash() const { return rep->hash; }
+
+ const char* data() const { return sym; }
+ operator const char* () const { return sym; }
+
+ bool contains(char c) const;
+ bool contains(const char* s) const;
+
+ bool containsAnyOf(const char* charSet) const;
+
+ int indexOf(char c) const;
+ int indexOf(const char* s) const;
+
+ // mutation
+ void toLower();
+ void toUpper();
+
+ // substring
+ Text substring(int start, int length);
+ Text trim();
+ Text replace(const char* pattern, const char* substitution);
+
+private:
+ void clone();
+
+ const char* sym;
+ TextRep* rep;
+};
+
+// +-------------------------------------------------------------------+
+
+inline int Text::compare(const char* s) const
+{
+ if (rep->sensitive)
+ return strcmp(sym, s);
+ else
+ return _stricmp(sym, s);
+}
+
+inline int Text::compare(const Text& s) const
+{
+ if (rep->sensitive && s.rep->sensitive)
+ return strcmp(sym, s.sym);
+ else
+ return _stricmp(sym, s.sym);
+}
+
+// +-------------------------------------------------------------------+
+
+inline int operator==(const Text& l, const Text& r) {
+ return (l.length() == r.length()) && (l.compare(r) == 0); }
+inline int operator!=(const Text& l, const Text& r) { return l.compare(r) != 0; }
+inline int operator< (const Text& l, const Text& r) { return l.compare(r) < 0; }
+inline int operator<=(const Text& l, const Text& r) { return l.compare(r) <= 0; }
+inline int operator> (const Text& l, const Text& r) { return l.compare(r) > 0; }
+inline int operator>=(const Text& l, const Text& r) { return l.compare(r) >= 0; }
+
+inline int operator==(const char* l, const Text& r) { return r.compare(l) == 0; }
+inline int operator!=(const char* l, const Text& r) { return r.compare(l) != 0; }
+inline int operator< (const char* l, const Text& r) { return r.compare(l) < 0; }
+inline int operator<=(const char* l, const Text& r) { return r.compare(l) <= 0; }
+inline int operator> (const char* l, const Text& r) { return r.compare(l) > 0; }
+inline int operator>=(const char* l, const Text& r) { return r.compare(l) >= 0; }
+
+inline int operator==( char* l, const Text& r) { return r.compare(l) == 0; }
+inline int operator!=( char* l, const Text& r) { return r.compare(l) != 0; }
+inline int operator< ( char* l, const Text& r) { return r.compare(l) < 0; }
+inline int operator<=( char* l, const Text& r) { return r.compare(l) <= 0; }
+inline int operator> ( char* l, const Text& r) { return r.compare(l) > 0; }
+inline int operator>=( char* l, const Text& r) { return r.compare(l) >= 0; }
+
+inline int operator==(const Text& l, const char* r) { return l.compare(r) == 0; }
+inline int operator!=(const Text& l, const char* r) { return l.compare(r) != 0; }
+inline int operator< (const Text& l, const char* r) { return l.compare(r) < 0; }
+inline int operator<=(const Text& l, const char* r) { return l.compare(r) <= 0; }
+inline int operator> (const Text& l, const char* r) { return l.compare(r) > 0; }
+inline int operator>=(const Text& l, const char* r) { return l.compare(r) >= 0; }
+
+inline int operator==(const Text& l, char* r) { return l.compare(r) == 0; }
+inline int operator!=(const Text& l, char* r) { return l.compare(r) != 0; }
+inline int operator< (const Text& l, char* r) { return l.compare(r) < 0; }
+inline int operator<=(const Text& l, char* r) { return l.compare(r) <= 0; }
+inline int operator> (const Text& l, char* r) { return l.compare(r) > 0; }
+inline int operator>=(const Text& l, char* r) { return l.compare(r) >= 0; }
+
+inline Text operator+(const char* l, const Text& r) { return Text(l) + r; }
+inline Text operator+( char* l, const Text& r) { return Text(l) + r; }
+
+// +-------------------------------------------------------------------+
+
+#endif Text_h
diff --git a/FoundationEx/ThreadSync.h b/FoundationEx/ThreadSync.h
index 274bb7f..7bf66c0 100644
--- a/FoundationEx/ThreadSync.h
+++ b/FoundationEx/ThreadSync.h
@@ -1,57 +1,81 @@
-/* Project nGen
- John DiCamillo
- Copyright © 1997-2001. All Rights Reserved.
-
- SUBSYSTEM: foundation
- FILE: ThreadSync.h
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Declaration of the ThreadSync class
-*/
-
-#ifndef ThreadSync_h
-#define ThreadSync_h
-
-#include <windows.h>
-
-// +-------------------------------------------------------------------+
-
-class ThreadSync
-{
-#if defined(_MT) // MULTITHREADED: WITH SYNC ------------
- CRITICAL_SECTION sync;
-
-public:
- ThreadSync() { ::InitializeCriticalSection(&sync); }
- ~ThreadSync() { ::DeleteCriticalSection(&sync); }
-
- void acquire() { ::EnterCriticalSection(&sync); }
- void release() { ::LeaveCriticalSection(&sync); }
-
-#else // SINGLE THREADED: NO SYNC ------------
-
-public:
- ThreadSync() { }
- ~ThreadSync() { }
-
- void acquire() { }
- void release() { }
-
-#endif
-};
-
-// +-------------------------------------------------------------------+
-
-class AutoThreadSync
-{
-public:
- AutoThreadSync(ThreadSync& s) : sync(s) { sync.acquire(); }
- ~AutoThreadSync() { sync.release(); }
-private:
- ThreadSync& sync;
-};
-
-#endif ThreadSync_h
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: foundation
+ FILE: ThreadSync.h
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Declaration of the ThreadSync class
+*/
+
+#ifndef ThreadSync_h
+#define ThreadSync_h
+
+#include <windows.h>
+
+// +-------------------------------------------------------------------+
+
+class ThreadSync
+{
+#if defined(_MT) // MULTITHREADED: WITH SYNC ------------
+ CRITICAL_SECTION sync;
+
+public:
+ ThreadSync() { ::InitializeCriticalSection(&sync); }
+ ~ThreadSync() { ::DeleteCriticalSection(&sync); }
+
+ void acquire() { ::EnterCriticalSection(&sync); }
+ void release() { ::LeaveCriticalSection(&sync); }
+
+#else // SINGLE THREADED: NO SYNC ------------
+
+public:
+ ThreadSync() { }
+ ~ThreadSync() { }
+
+ void acquire() { }
+ void release() { }
+
+#endif
+};
+
+// +-------------------------------------------------------------------+
+
+class AutoThreadSync
+{
+public:
+ AutoThreadSync(ThreadSync& s) : sync(s) { sync.acquire(); }
+ ~AutoThreadSync() { sync.release(); }
+private:
+ ThreadSync& sync;
+};
+
+#endif ThreadSync_h