00001 00002 #include "skype-ptr-dict.h" 00003 #include <stdio.h> 00004 00005 #define SIZE 17 00006 00007 /** \cond INTERNAL */ 00008 class SEPtrDict::Element 00009 { 00010 public: 00011 Element(const SEString& k, const void* v); 00012 00013 public: 00014 Element* next; 00015 SEString key; 00016 const void* value; 00017 }; 00018 00019 class SEPtrDict::Data 00020 { 00021 public: 00022 Data(); 00023 00024 public: 00025 Element* dict[SIZE]; 00026 unsigned int ref; 00027 size_t size; 00028 bool dirty; 00029 Element** quick_list; 00030 SEMutex lock; 00031 }; 00032 00033 SEPtrDict::Element::Element(const SEString& k, const void* v) 00034 :next(0), 00035 key(k), 00036 value(v) 00037 { 00038 00039 } 00040 00041 SEPtrDict::Data::Data() 00042 :dirty(true), 00043 quick_list(0) 00044 { 00045 00046 } 00047 /** \endcond */ 00048 00049 SEPtrDict::SEPtrDict() 00050 :d(0) 00051 { 00052 00053 } 00054 00055 SEPtrDict::SEPtrDict(const SEPtrDict& dict) 00056 :d(0) 00057 { 00058 *this = dict; 00059 } 00060 00061 SEPtrDict::~SEPtrDict() 00062 { 00063 d_unref(); 00064 } 00065 00066 void SEPtrDict::insert(const SEString& key, const void* new_value) 00067 { 00068 if (key.isNull()) 00069 return; 00070 00071 detach(); 00072 00073 if (0 == d) { 00074 d = new Data(); 00075 00076 d->ref = 1; 00077 00078 for (size_t n = 0; n < SIZE; n++) 00079 d->dict[n] = 0; 00080 } 00081 00082 d->dirty = true; 00083 00084 unsigned int h = key.hash(SIZE); 00085 00086 Element** e = &(d->dict[h]); 00087 00088 while (*e) 00089 e = &((*e)->next); 00090 00091 *e = new Element(key, new_value); 00092 } 00093 00094 const void*& SEPtrDict::find(const SEString& key, unsigned int offset) const 00095 { 00096 static const void* null = 0; 00097 00098 if (0 == d) 00099 return null; 00100 00101 unsigned int h = key.hash(SIZE); 00102 00103 Element** e = &(d->dict[h]); 00104 00105 while (*e) { 00106 if ((*e)->key == key) { 00107 if (0 == offset) 00108 return (*e)->value; 00109 else 00110 offset--; 00111 } 00112 00113 e = &((*e)->next); 00114 } 00115 00116 return null; 00117 } 00118 00119 SEPtrDict& SEPtrDict::operator=(const SEPtrDict& dict) 00120 { 00121 const_cast<SEPtrDict&>(dict).d_ref(); 00122 00123 d_unref(); 00124 00125 d = dict.d; 00126 00127 return *this; 00128 } 00129 00130 /** \cond INTERNAL */ 00131 void SEPtrDict::d_ref() 00132 { 00133 if (0 == d) 00134 return; 00135 00136 d->lock.Acquire(); 00137 00138 d->ref++; 00139 00140 d->lock.Release(); 00141 } 00142 00143 void SEPtrDict::d_unref() 00144 { 00145 if (0 == d) 00146 return; 00147 00148 SEMutex* lock = &d->lock; 00149 00150 lock->Acquire(); 00151 00152 if (d->ref > 1) 00153 d->ref--; 00154 else { 00155 Data* tmp_d = d; 00156 d = 0; 00157 00158 lock->Release(); 00159 00160 for (size_t n = 0; n < SIZE; n++) { 00161 while (tmp_d->dict[n]) { 00162 Element* tmp = tmp_d->dict[n]->next; 00163 00164 delete tmp_d->dict[n]; 00165 00166 tmp_d->dict[n] = tmp; 00167 } 00168 } 00169 00170 if (tmp_d->quick_list) 00171 delete[] tmp_d->quick_list; 00172 00173 delete tmp_d; 00174 00175 return; 00176 } 00177 00178 lock->Release(); 00179 } 00180 00181 void SEPtrDict::detach() 00182 { 00183 if (0 == d) 00184 return; 00185 00186 if (1 == d->ref) 00187 return; 00188 00189 Data* d_new = new Data(); 00190 00191 d_new->ref = 1; 00192 00193 size_t n; 00194 for (n = 0; n < SIZE; n++) 00195 d_new->dict[n] = 0; 00196 00197 for (n = 0; n < SIZE; n++) { 00198 Element** from = &(d->dict[n]); 00199 Element** to = &(d_new->dict[n]); 00200 00201 while (*from) { 00202 *to = new Element((*from)->key, (*from)->value); 00203 00204 from = &((*from)->next); 00205 to = &((*to)->next); 00206 } 00207 } 00208 00209 d_unref(); 00210 00211 d = d_new; 00212 } 00213 00214 /** \endcond */ 00215 00216 size_t SEPtrDict::size() const 00217 { 00218 if (0 == d) 00219 return 0; 00220 00221 if (d->dirty) { 00222 if (d->quick_list) 00223 delete[] d->quick_list; 00224 00225 d->size = 0; 00226 00227 size_t n; 00228 for (n = 0; n < SIZE; n++) { 00229 Element** e = &(d->dict[n]); 00230 00231 while (*e) { 00232 d->size++; 00233 00234 e = &((*e)->next); 00235 } 00236 } 00237 00238 d->quick_list = new Element*[d->size]; 00239 00240 size_t c = 0; 00241 00242 for (n = 0; n < SIZE; n++) { 00243 Element** e = &(d->dict[n]); 00244 00245 while (*e) { 00246 d->quick_list[c++] = *e; 00247 00248 e = &((*e)->next); 00249 } 00250 } 00251 00252 d->dirty = false; 00253 } 00254 00255 return d->size; 00256 } 00257 00258 const void*& SEPtrDict::operator[](size_t i) const 00259 { 00260 static const void* null = 0; 00261 00262 if (0 == d) 00263 return null; 00264 00265 if (i >= size()) 00266 return null;; 00267 00268 return d->quick_list[i]->value; 00269 } 00270 00271 SEString SEPtrDict::keyAt(size_t i) const 00272 { 00273 if (0 == d) 00274 return SEString(); 00275 00276 if (i >= size()) 00277 return SEString(); 00278 00279 return d->quick_list[i]->key; 00280 } 00281 00282 SEStringList SEPtrDict::keys() { 00283 SEStringList result; 00284 int d_size = size(); 00285 if (d && d->quick_list) { 00286 for (int i = 0; i < d_size; i++) { 00287 result.append(d->quick_list[i]->key); 00288 } 00289 } 00290 return result; 00291 }
(c) Skype Technologies S.A. Confidential/Proprietary
Last updated: Fri Jan 27 2012