1 // Copyright 2009 The Archiveopteryx Developers <info@aox.org>
2 
3 #include "estringlist.h"
4 
5 #include "dict.h"
6 
7 
8 /*! \class EStringList estringlist.h
9 
10     The EStringList class is a List of EString object, offering a few
11     convenience functions such as join() and removeDuplicates().
12 */
13 
14 
15 /*! Constructs an empty List of (pointers to) EString objects. */
16 
EStringList()17 EStringList::EStringList()
18 {
19 }
20 
21 
22 /*! \fn void EStringList::append( EString * s )
23 
24     Appends the EString \a s to this EStringList. (Inline reimplementation
25     to work around the shadowing rules of C++.)
26 */
27 
28 
29 
30 /*! This version of append() makes a copy of \a s and appends that
31     copy to the list.
32 */
33 
append(const EString & s)34 void EStringList::append( const EString & s )
35 {
36     List<EString>::append( new EString( s ) );
37 }
38 
39 
40 /*! This version of append() makes a EString copy of \a s and appends
41     that copy to the list.
42 */
43 
append(const char * s)44 void EStringList::append( const char * s )
45 {
46     List<EString>::append( new EString( s ) );
47 }
48 
49 
50 /*! \fn void EStringList::append( const EStringList & l )
51 
52     Appends the contents of the EStringList \a l to this EStringList.
53 */
54 
55 
56 /*! Returns a string containing every EString in this list, with \a
57     separator between the items.
58 
59     If this List isEmpty(), this function returns an empty EString.
60 */
61 
join(const EString & separator) const62 EString EStringList::join( const EString & separator ) const
63 {
64     EString r;
65     Iterator it( this );
66     uint l = 0;
67     while ( it ) {
68         l = l + it->length() + separator.length();
69         ++it;
70     }
71     r.reserve( l );
72     it = first();
73     while ( it ) {
74         r.append( *it );
75         ++it;
76         if ( it )
77             r.append( separator );
78     }
79     return r;
80 }
81 
82 
83 /*! This function splits \a s on the separator \a c, and returns a non-0
84     pointer to a list of the resulting strings. Consecutive occurrences
85     of \a c cause the list to contain empty elements.
86 */
87 
split(char c,const EString & s)88 EStringList *EStringList::split( char c, const EString &s )
89 {
90     EStringList *l = new EStringList;
91 
92     int n = 0;
93     int last = 0;
94     do {
95         EString w;
96         n = s.find( c, last );
97         if ( n >= 0 ) {
98             w = s.mid( last, n-last );
99             n++;
100         }
101         else {
102             w = s.mid( last );
103         }
104         last = n;
105         l->append( w );
106     }
107     while ( last > 0 );
108 
109     return l;
110 }
111 
112 
113 /*! Removes duplicate entries from the list. If \a caseSensitive is
114     true (this is the default), strings are compared exactly. If \a
115     caseSensitive is false, ASCII A-Z are treated as equal to a-z.
116 
117     When two more more strings are equal, removeDuplicates() leaves
118     the first and removes the second and later copies.
119 */
120 
removeDuplicates(bool caseSensitive)121 void EStringList::removeDuplicates( bool caseSensitive )
122 {
123     Dict<uint> e;
124     uint tmp = 1;
125     Iterator i( this );
126     while ( i ) {
127         EString s = *i;
128         if ( !caseSensitive )
129             s = s.lower();
130         if ( e.contains( s ) ) {
131             take( i );
132         }
133         else {
134             ++i;
135             e.insert( s, &tmp );
136         }
137     }
138 }
139 
140 
141 /*! Returns true if \a s occurs in this string list, and false if not. */
142 
contains(const EString & s) const143 bool EStringList::contains( const EString & s ) const
144 {
145     Iterator i( this );
146     while ( i && s != *i )
147         ++i;
148     if ( i )
149         return true;
150     return false;
151 }
152 
153 
caseSensitively(const void * a,const void * b)154 static int caseSensitively( const void * a, const void * b )
155 {
156     const EString ** ea = (const EString**)a;
157     const EString ** eb = (const EString**)b;
158     return (*ea)->compare( **eb );
159 }
160 
161 
162 /*! Returns a new list containing the same items as this, but
163     sorted. The sorting is case sensitive.
164 */
165 
sorted() const166 EStringList * EStringList::sorted() const
167 {
168     return reinterpret_cast<EStringList*>(
169         List<EString>::sorted( caseSensitively ) );
170 }
171