- Main Page
- Related Pages
- Classes
- Files
- Examples

- File List
- File Members

# skype-string-list.cpp

Go to the documentation of this file.

    00001
    00002 #include "skype-string-list.h"
    00003 #include <stdio.h>
    00004
    00005 /** \cond INTERNAL */
    00006 class SEStringList::Element
    00007 {
    00008 public:
    00009         Element();
    00010
    00011 public:
    00012         SEString str;
    00013         Element* next;
    00014 };
    00015
    00016 class SEStringList::Data
    00017 {
    00018 public:
    00019         unsigned int ref;
    00020         Element* list;
    00021         Element* last;
    00022         bool dirty;
    00023         Element** quick_list;
    00024         size_t size;
    00025         SEMutex lock;
    00026 };
    00027
    00028 SEStringList::Element::Element()
    00029                 :next(0)
    00030 {
    00031
    00032 }
    00033 /** \endcond */
    00034
    00035 SEStringList::SEStringList()
    00036                 :d(0)
    00037 {
    00038
    00039 }
    00040
    00041 SEStringList::SEStringList(const SEStringList& sl)
    00042                 :d(0)
    00043 {
    00044         *this = sl;
    00045 }
    00046
    00047 SEStringList::~SEStringList()
    00048 {
    00049         d_unref();
    00050 }
    00051
    00052 /** \cond INTERNAL */
    00053 void SEStringList::init()
    00054 {
    00055         if (d)
    00056                 return;
    00057
    00058         d = new Data();
    00059         d->ref = 1;
    00060         d->list = 0;
    00061         d->dirty = true;
    00062         d->size = 0;
    00063         d->quick_list = 0;
    00064 }
    00065 /** \endcond */
    00066
    00067 SEStringList& SEStringList::append(const SEString& str)
    00068 {
    00069         if (str.isNull()) {
    00070                 return append("")/**this*/;
    00071         }
    00072
    00073         detach();
    00074
    00075         if (0 == d) {
    00076                 init();
    00077
    00078                 d->list = new Element();
    00079                 d->list->str = str;
    00080                 d->last = d->list;
    00081         } else {
    00082                 d->dirty = true;
    00083                 d->last->next = new Element();
    00084                 d->last->next->str = str;
    00085                 d->last = d->last->next;
    00086         }
    00087
    00088         return *this;
    00089 }
    00090
    00091 #if 0
    00092 SEStringList& SEStringList::prepend(const SEString& str)
    00093 {
    00094         if (str.isNull())
    00095                 return *this;
    00096
    00097         detach();
    00098
    00099         if (0 == d) {
    00100                 init();
    00101
    00102                 d->list = new Element();
    00103                 d->list->str = str;
    00104                 d->last = d->list;
    00105         } else {
    00106                 d->dirty = true;
    00107
    00108                 Element* n = new Element();
    00109
    00110                 n->str = str;
    00111                 n->next = d->list;
    00112                 d->list = n;
    00113         }
    00114
    00115         return *this;
    00116 }
    00117 #endif
    00118
    00119 SEString SEStringList::peek()
    00120 {
    00121         detach();
    00122
    00123         if (0 == d)
    00124                 return SEString();
    00125
    00126         d->dirty = true;
    00127
    00128         SEString ret = d->list->str;
    00129
    00130         Element* next = d->list->next;
    00131
    00132         delete d->list;
    00133
    00134         d->list = next;
    00135
    00136         if (0 == d->list) {
    00137                 delete d;
    00138                 d = 0;
    00139         }
    00140
    00141         return ret;
    00142 }
    00143
    00144 size_t SEStringList::size() const
    00145 {
    00146         if (0 == d)
    00147                 return 0;
    00148
    00149         if (!d->dirty)
    00150                 return d->size;
    00151
    00152         if (d->quick_list)
    00153                 delete[] d->quick_list;
    00154
    00155         // first pass - count elements
    00156         d->size = 0;
    00157
    00158         Element* e = d->list;
    00159
    00160         do {
    00161                 d->size++;
    00162                 e = e->next;
    00163         } while (e);
    00164
    00165         // second pass - fill quick access vector
    00166         d->quick_list = new Element*[d->size];
    00167
    00168         e = d->list;
    00169         size_t n = 0;
    00170
    00171         while (e) {
    00172                 d->quick_list[n++] = e;
    00173
    00174                 e = e->next;
    00175         }
    00176
    00177         d->dirty = false;
    00178
    00179         return d->size;
    00180 }
    00181
    00182 const SEString &SEStringList::operator[](size_t n) const
    00183 {
    00184         if ((0 == d) || (n >= size()))
    00185                 return empty;
    00186
    00187         return d->quick_list[n]->str;
    00188 }
    00189
    00190 SEString SEStringList::operator[](size_t n)
    00191 {
    00192         if ((0 == d) || (n >= size()))
    00193                 return SEString();
    00194
    00195         // we have already called size() so we are supposed to be "clean"
    00196
    00197         return d->quick_list[n]->str;
    00198 }
    00199
    00200 SEStringList& SEStringList::operator=(const SEStringList& sl)
    00201 {
    00202         const_cast<SEStringList&>(sl).d_ref();
    00203         d_unref();
    00204
    00205         d = sl.d;
    00206
    00207
    00208         return *this;
    00209 }
    00210
    00211 /** \cond INTERNAL */
    00212 void SEStringList::d_ref()
    00213 {
    00214         if (0 == d)
    00215                 return;
    00216
    00217         d->lock.Acquire();
    00218
    00219         d->ref++;
    00220
    00221         d->lock.Release();
    00222 }
    00223
    00224 void SEStringList::d_unref()
    00225 {
    00226         if (0 == d)
    00227                 return;
    00228
    00229         SEMutex* lock = &d->lock;
    00230
    00231         lock->Acquire();
    00232
    00233         if (d->ref > 1)
    00234                 d->ref--;
    00235         else {
    00236                 Data* tmp_d = d;
    00237                 d = 0;
    00238                 lock->Release();
    00239
    00240                 Element* tmp = tmp_d->list;
    00241
    00242                 while (tmp) {
    00243                         Element* next = tmp->next;
    00244
    00245                         delete tmp;
    00246
    00247                         tmp = next;
    00248                 }
    00249
    00250                 if (tmp_d->quick_list)
    00251                         delete[] tmp_d->quick_list;
    00252
    00253                 delete tmp_d;
    00254                 return;
    00255         }
    00256
    00257         lock->Release();
    00258 }
    00259
    00260 void SEStringList::detach()
    00261 {
    00262         if (0 == d)
    00263                 return;
    00264
    00265         d->lock.Acquire();
    00266
    00267         if (1 != d->ref) {
    00268
    00269                 Data* d_new = new Data();
    00270
    00271                 d_new->ref = 1;
    00272                 d_new->dirty = true;
    00273                 d_new->quick_list = 0;
    00274
    00275                 d_new->list = new Element;
    00276                 d_new->list->str = d->list->str;
    00277
    00278                 Element* from = d->list->next;
    00279                 Element* to = d_new->list;
    00280
    00281                 while (from) {
    00282                         to->next = new Element;
    00283                         to->next->str = from->str;
    00284
    00285                         to = to->next;
    00286                         from = from->next;
    00287                 }
    00288
    00289                 d_new->last = to;
    00290
    00291                 d->lock.Release();
    00292
    00293                 d_unref();
    00294
    00295                 d = d_new;
    00296
    00297                 return;
    00298         }
    00299
    00300         d->lock.Release();
    00301 }
    00302 /** \endcond */
    00303
    00304 SEString SEStringList::join(const SEString& sep, bool escape_args) const
    00305 {
    00306         SEString ret;
    00307
    00308         if (!size())
    00309                 return ret;
    00310
    00311         ret += escape_args ? operator[](0).escape() : operator[](0);
    00312
    00313         for (size_t n = 1; n < size(); n++)
    00314                 ret += sep + (escape_args ? operator[](n).escape() : operator[](n));
    00315
    00316         return ret;
    00317 }
    00318
    00319 SEStringList SEStringList::split(const SEString& str, char sep, char esc)
    00320 {
    00321         SEStringList ret;
    00322         int from = 0;
    00323         int cur = 0;
    00324         int* quotes = NULL;
    00325
    00326         const size_t len = str.length();
    00327
    00328         if (len == 0)
    00329                 return ret;
    00330
    00331         if (esc) {
    00332                 int q = ('"' == str[0]) ? 1 : 0;
    00333                 if ((q) && ('"' == str[1]))
    00334                         return ret;
    00335
    00336                 // we can initialize quotes only here because it's never used if esc == null
    00337                 quotes = new int[len];
    00338
    00339                 quotes[0] = q;
    00340
    00341                 for (size_t n = 1; n < len; n++) {
    00342                         if (str[n] == '"') {
    00343                                 if (str[n - 1] != esc) // " is not escaped
    00344                                         quotes[n] = ++q;
    00345                                 else { // " is escaped
    00346                                         size_t i = n - 1;
    00347                                         // to detect the case where we have some escaped \ just before the "
    00348                                         while (i && (str[i] == esc)) i--;
    00349                                         if ((n - i) % 2) // even number of /, " is not escaped
    00350                                                 quotes[n] = ++q;
    00351                                         else             // odd number of /, " is escaped
    00352                                                 quotes[n] = q;
    00353                                 }
    00354
    00355                         } else
    00356                                 quotes[n] = q;
    00357                 }
    00358         }
    00359
    00360         // skip trailing separators
    00361         while (str[cur] == sep) {
    00362                 from++;
    00363                 cur++;
    00364         }
    00365
    00366         cur++;
    00367
    00368         while (cur <= (int)len) {
    00369                 // the case when we go out of bounds is when we have escaped separator
    00370                 // before end of the string
    00371       if (cur == (int)len) {
    00372                         ret.append(str.substr(from, cur - 1));
    00373
    00374                         break;
    00375                 }
    00376
    00377                 if ((str[cur] == sep)) {
    00378                         // here we may go out of bounds (handled above)
    00379                         if (esc && ((str[cur - 1] == esc) || (quotes[cur] % 2))) {
    00380                                 cur++;
    00381
    00382                                 continue;
    00383                         }
    00384
    00385                         ret.append(str.substr(from, cur - 1));
    00386
    00387                         while ((str[cur] == sep) && (cur < (int)len))
    00388                                 cur++;
    00389
    00390                         if (cur >= (int)len)
    00391                                 break;
    00392
    00393                         from = cur++;
    00394
    00395                         continue;
    00396                 }
    00397
    00398                 if (cur == (int)len - 1) {
    00399                         ret.append(str.substr(from, cur));
    00400
    00401                         break;
    00402                 }
    00403
    00404                 cur++;
    00405         }
    00406
    00407         if (esc)
    00408                 delete[] quotes;
    00409
    00410         return ret;
    00411 }
    00412
    00413
    00414 void SEStringList::resize(const unsigned int new_size)
    00415 {
    00416         if (size() == new_size) return;
    00417         if (new_size == 0) {
    00418                 clear();
    00419                 return;
    00420         }
    00421
    00422         detach();
    00423         unsigned int cursize = size(); //updates quick_list
    00424
    00425         if (cursize > new_size) { //shrink
    00426
    00427                 Element* elem_last = d->quick_list[new_size-1];
    00428                 elem_last->next = 0;
    00429                 d->last = elem_last;
    00430
    00431                 for (unsigned int n = new_size; n < cursize; n++) {
    00432                         delete d->quick_list[n];
    00433                 }
    00434
    00435         } else {   //grow
    00436
    00437                 while (cursize < new_size) {
    00438                         if (0 == d) {
    00439                                 init();
    00440                                 d->list = new Element();
    00441                                 d->list->str = "";
    00442                                 d->last = d->list;
    00443                         } else {
    00444                                 d->last->next = new Element();
    00445                                 d->last->next->str = "";
    00446                                 d->last = d->last->next;
    00447                         }
    00448
    00449                         cursize++;
    00450                 }
    00451         }
    00452
    00453         d->dirty = true;
    00454 }
    00455
    00456 int SEStringList::find_pos(const SEString& val)
    00457 {
    00458         int len = size();
    00459         for (int n = 0; n < len; n++) {
    00460                 if (d->quick_list[n]->str == val) {
    00461                         return n;
    00462                 }
    00463         }
    00464
    00465         return -1;
    00466 }
    00467
    00468 bool SEStringList::contains(const SEString& val)
    00469 {
    00470         return (find_pos(val) >= 0);
    00471 }
    00472
    00473 bool SEStringList::remove_val(const SEString& val)
    00474 {
    00475         int pos = find_pos(val);
    00476         if (pos >= 0) return remove_pos(pos);
    00477
    00478         return false;
    00479 }
    00480
    00481 bool SEStringList::remove_pos(const unsigned int pos)
    00482 {
    00483         if (0 == d || pos >= size()) return false;
    00484
    00485         detach();
    00486         unsigned int cursize = size();//updates quick_list
    00487
    00488         Element* elem_del = d->quick_list[pos];
    00489         Element* elem_next = elem_del->next;
    00490         Element* elem_prev = pos == 0 ? 0 : d->quick_list[pos-1];
    00491
    00492         if (pos == 0) {//first
    00493                 delete elem_del;
    00494                 d->list = elem_next;
    00495         } else if (pos == cursize -1) { //last
    00496                 delete elem_del;
    00497                 elem_prev->next = 0;
    00498                 d->last = elem_prev;
    00499         } else {
    00500                 delete elem_del;
    00501                 elem_prev->next = elem_next;
    00502         }
    00503
    00504         d->dirty = true;
    00505         if (0 == d->list) {
    00506                 delete d;
    00507                 d = 0;
    00508         }
    00509
    00510         return true;
    00511 }
    00512
    00513 void SEStringList::clear()
    00514 {
    00515         if (0 == d) {
    00516                 return;
    00517         }
    00518
    00519         detach();
    00520
    00521         for (unsigned int n = 0; n < size(); n++) {
    00522                 delete d->quick_list[n];
    00523         }
    00524
    00525         if (d->quick_list)
    00526                 delete[] d->quick_list;
    00527
    00528         delete d;
    00529
    00530         d = 0;
    00531 }
    00532

All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

(c) Skype Technologies S.A. Confidential/Proprietary

Last updated: Fri Mar 16 2012