ppodlist.cxx (3814B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #include "ptypes.h" 13 14 15 namespace ptypes { 16 17 18 void _podlist::idxerror() 19 { 20 fatal(CRIT_FIRST + 30, "List index out of bounds"); 21 } 22 23 24 _podlist::_podlist(int iitemsize) 25 : list(0), count(0), capacity(0), itemsize(iitemsize) 26 { 27 if (itemsize <= 0 || itemsize > 255) 28 fatal(CRIT_FIRST + 37, "Invalid item size for podlist"); 29 } 30 31 32 _podlist::~_podlist() 33 { 34 set_count(0); 35 } 36 37 38 void _podlist::set_capacity(int newcap) 39 { 40 if (newcap != capacity) 41 { 42 if (newcap < count) 43 fatal(CRIT_FIRST + 36, "List capacity can't be smaller than count"); 44 list = memrealloc(list, newcap * itemsize); 45 capacity = newcap; 46 } 47 } 48 49 50 void _podlist::grow() 51 { 52 if (capacity > count) 53 return; 54 set_capacity(capacity == 0 ? 4 : ((capacity + 1) / 2) * 3); 55 } 56 57 58 void _podlist::set_count(int newcount, bool zero) 59 { 60 if (newcount > count) 61 { 62 if (newcount > capacity) 63 set_capacity(newcount); 64 if (zero) 65 memset(doget(count), 0, (newcount - count) * itemsize); 66 count = newcount; 67 } 68 else if (newcount < count) 69 { 70 if (newcount < 0) 71 // wrong newcount: we don't want to generate an error here. 72 // instead, we'll set count to 0 and wait until some other 73 // operation raises an error 74 newcount = 0; 75 count = newcount; 76 if (count == 0) 77 set_capacity(0); 78 } 79 } 80 81 82 // doXXX() methods do not perform bounds checking; used internally 83 // where index is guaranteed to be valid 84 85 void* _podlist::doins(int index) 86 { 87 grow(); 88 pchar s = pchar(doget(index)); 89 if (index < count) 90 memmove(s + itemsize, s, (count - index) * itemsize); 91 count++; 92 return s; 93 } 94 95 96 void _podlist::doins(int index, const _podlist& t) 97 { 98 if (&t == this) 99 return; 100 if (index == count) 101 add(t); 102 else 103 { 104 if (itemsize != t.itemsize) 105 fatal(CRIT_FIRST + 35, "Incompatible list"); 106 if (t.count == 0) 107 return; 108 int ocnt = count; 109 set_count(ocnt + t.count); 110 pchar s = pchar(doget(index)); 111 memmove(s + t.count * itemsize, s, (ocnt - index) * itemsize); 112 memcpy(s, t.list, t.count * itemsize); 113 } 114 } 115 116 117 void* _podlist::add() 118 { 119 grow(); 120 return doget(count++); 121 } 122 123 124 void _podlist::add(const _podlist& t) 125 { 126 if (count == 0) 127 operator =(t); 128 else 129 { 130 if (itemsize != t.itemsize) 131 fatal(CRIT_FIRST + 35, "Incompatible list"); 132 int ocnt = count; 133 int tcnt = t.count; 134 set_count(ocnt + tcnt); 135 memcpy(doget(ocnt), t.list, tcnt * itemsize); 136 } 137 } 138 139 140 _podlist& _podlist::operator =(const _podlist& t) 141 { 142 if (&t != this) 143 { 144 if (itemsize != t.itemsize) 145 fatal(CRIT_FIRST + 35, "Incompatible list"); 146 set_count(t.count); 147 pack(); 148 memcpy(list, t.list, count * itemsize); 149 } 150 return *this; 151 } 152 153 154 void _podlist::dodel(int index) 155 { 156 count--; 157 if (index < count) 158 { 159 pchar s = pchar(doget(index)); 160 memmove(s, s + itemsize, (count - index) * itemsize); 161 } 162 else if (count == 0) 163 set_capacity(0); 164 } 165 166 167 void _podlist::dodel(int index, int delcount) 168 { 169 if (delcount <= 0) 170 return; 171 if (index + delcount > count) 172 delcount = count - index; 173 count -= delcount; 174 if (index < count) 175 { 176 pchar s = pchar(doget(index)); 177 memmove(s, s + delcount * itemsize, (count - index) * itemsize); 178 } 179 else if (count == 0) 180 set_capacity(0); 181 } 182 183 184 void _podlist::dopop() 185 { 186 if (--count == 0) 187 set_capacity(0); 188 } 189 190 191 } 192