00001 /* 00002 Copyright (C) 2002-2004 The Pentagram team 00003 00004 This program is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU General Public License 00006 as published by the Free Software Foundation; either version 2 00007 of the License, or (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #ifndef UCLIST_H 00020 #define UCLIST_H 00021 00022 #include <vector> 00023 #include <string> 00024 00025 class IDataSource; 00026 class ODataSource; 00027 00028 // stringlists: elementsize = 2, each element is actually a stringref 00029 // see for example the 0x0E opcode: there is no way to see if the 00030 // created list is a stringlist or not 00031 // the opcodes which do need a distinction have a operand for this. 00032 00033 // Question: how are unionList/substractList supposed to know what to do? 00034 // their behaviour differs if this is a stringlist 00035 00036 // Question: does substractList remove _all_ occurences of elements or only 1? 00037 00038 class UCList 00039 { 00040 std::vector<uint8> elements; 00041 unsigned int elementsize; 00042 unsigned int size; 00043 00044 public: 00045 UCList(unsigned int elementsize_, unsigned int capacity=0) : 00046 elementsize(elementsize_), size(0) 00047 { 00048 if (capacity > 0) 00049 elements.reserve(elementsize * capacity); 00050 } 00051 00052 ~UCList() { 00053 // Slight problem: we don't know if we're a stringlist. 00054 // So we need to hope something else has ensured any strings 00055 // are already freed. 00056 free(); 00057 } 00058 00059 const uint8* operator[](uint32 index) { 00060 // check that index isn't out of bounds... 00061 return &(elements[index * elementsize]); 00062 } 00063 00064 uint16 getuint16(uint32 index) { 00065 assert(elementsize == 2); 00066 uint16 t = elements[index * elementsize]; 00067 t += elements[index * elementsize + 1] << 8; 00068 return t; 00069 } 00070 00071 void append(const uint8* e) { 00072 elements.resize((size + 1) * elementsize); 00073 for (unsigned int i = 0; i < elementsize; i++) 00074 elements[size*elementsize + i] = e[i]; 00075 size++; 00076 } 00077 00078 void remove(const uint8* e) { 00079 // do we need to erase all occurences of e or just the first one? 00080 // (deleting all, currently) 00081 for (unsigned int i = 0; i < size; i++) { 00082 bool equal = true; 00083 for (unsigned int j = 0; j < elementsize && equal; j++) 00084 equal = (elements[i*elementsize + j] == e[j]); 00085 if (!equal) { 00086 elements.erase(elements.begin()+i*elementsize, 00087 elements.begin()+(i+1)*elementsize); 00088 size--; 00089 i--; // back up a bit 00090 } 00091 } 00092 } 00093 00094 bool inList(const uint8* e) { 00095 for (unsigned int i = 0; i < size; i++) { 00096 bool equal = true; 00097 for (unsigned int j = 0; j < elementsize && equal; j++) 00098 equal = (elements[i*elementsize + j] == e[j]); 00099 if (equal) 00100 return true; 00101 } 00102 return false; 00103 } 00104 00105 void appendList(UCList& l) { 00106 // need to check if elementsizes match... 00107 elements.reserve(elementsize * (size + l.size)); 00108 unsigned int lsize = l.size; 00109 for (unsigned int i = 0; i < lsize; i++) 00110 append(l[i]); 00111 } 00112 void unionList(UCList& l) { // like append, but remove duplicates 00113 // need to check if elementsizes match... 00114 elements.reserve(elementsize * (size + l.size)); 00115 for (unsigned int i = 0; i < l.size; i++) 00116 if (!inList(l[i])) 00117 append(l[i]); 00118 } 00119 void substractList(UCList& l) { 00120 for (unsigned int i = 0; i < l.size; i++) 00121 remove(l[i]); 00122 } 00123 00124 void free() { elements.clear(); size = 0; } 00125 uint32 getSize() const { return size; } 00126 unsigned int getElementSize() const { return elementsize; } 00127 00128 void assign(uint32 index, const uint8* e) { 00129 // need to check that index isn't out-of-bounds? (or grow list?) 00130 for (unsigned int i = 0; i < elementsize; i++) 00131 elements[index*elementsize+i] = e[i]; 00132 } 00133 00134 void copyList(UCList& l) { // deep copy for list 00135 free(); 00136 appendList(l); 00137 } 00138 00139 void freeStrings(); 00140 void copyStringList(UCList& l); 00141 void unionStringList(UCList& l); 00142 void substractStringList(UCList& l); 00143 bool stringInList(uint16 str); 00144 void assignString(uint32 index, uint16 str); 00145 void removeString(uint16 str, bool nodel=false); 00146 00147 uint16 getStringIndex(uint32 index); 00148 00149 void save(ODataSource* ods); 00150 bool load(IDataSource* ids, uint32 version); 00151 00152 private: 00153 std::string& getString(uint32 index); 00154 }; 00155 00156 #endif