|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32std.h> |
|
17 #include "stringpoolimplementation.h" |
|
18 |
|
19 |
|
20 |
|
21 EXPORT_C void RStringBase::Close() |
|
22 /** Closes a string. |
|
23 |
|
24 You must close every string you open. In other words, every call to RStringBase::Copy(), |
|
25 RStringPool::OpenStringL() and RStringPool::OpenFStringL() must be matched |
|
26 by a close. |
|
27 |
|
28 Strings created through RStringPool::String() or RStringPool::StringF() with |
|
29 an integer argument need not be closed (but closing is harmless). |
|
30 |
|
31 Strings created through RStringPool::String() or RStringPool::StringF() with |
|
32 a StringToken or StringTokenF argument must not be closed, as they're just |
|
33 changing the external representation. */ |
|
34 { |
|
35 if (iVal) |
|
36 //harmless for empty strings |
|
37 iPool.iImplementation->Close(RStringTokenEither(iVal)); |
|
38 // invalidate the string if it's a dinamic one otherwise do nothing |
|
39 if(!StringUtils::IsTableEntry(this->iVal)) |
|
40 iVal=0U; |
|
41 } |
|
42 |
|
43 |
|
44 EXPORT_C RStringBase RStringBase::Copy() |
|
45 /** Copies a string. |
|
46 |
|
47 Both the original and the copy string must be separately closed. |
|
48 |
|
49 @return The string base. */ |
|
50 { |
|
51 if (iVal) |
|
52 iPool.iImplementation->IncrementCount(RStringTokenEither(iVal)); |
|
53 return *this; |
|
54 } |
|
55 |
|
56 |
|
57 /** Returns the content of the string |
|
58 */ |
|
59 EXPORT_C const TDesC8& RStringBase::DesC() const |
|
60 /** Gets the content of the string. |
|
61 |
|
62 @return Descriptor containing the content of the string. */ |
|
63 { |
|
64 // check for empty string |
|
65 if (iVal == 0) |
|
66 return KNullDesC8(); |
|
67 if (StringUtils::IsTableEntry(iVal)) |
|
68 { |
|
69 TInt index = StringUtils::TableIndex(iVal); |
|
70 TInt tableUid= StringUtils::TableUid(iVal); |
|
71 return iPool.iImplementation->TableLookup(index, tableUid); |
|
72 } |
|
73 else |
|
74 return *StringUtils::NodePtr(iVal)->iDes; |
|
75 } |
|
76 |
|
77 |
|
78 EXPORT_C TInt RStringBase::Index(const TStringTable& aTable) const |
|
79 /** Gets the enumeration value corresponding to this string. |
|
80 |
|
81 @param aTable String table to look in |
|
82 @return The string's enumeration value, or -1 if there is no such value |
|
83 @panic EStringTableNotFound If the table supplied is not found. This panic is raised in debug builds only, in release mode the behaviour is undefined*/ |
|
84 { |
|
85 //return an error for empty strings(i.e. with iVal=0 ) |
|
86 if(!this->iVal) |
|
87 return KErrNotFound; |
|
88 TInt tableId=iPool.iImplementation->TableUid(aTable); |
|
89 __ASSERT_DEBUG(tableId!=KErrNotFound,StringPoolPanic::Panic(StringPoolPanic::EStringTableNotFound)); |
|
90 // First check the iVal is part of the same table |
|
91 if (StringUtils::IsTableEntry(iVal)) |
|
92 { |
|
93 if (tableId==StringUtils::TableUid(iVal)) |
|
94 return StringUtils::TableIndex(iVal); |
|
95 } |
|
96 // Then check if the iVal is in the reverse duplicate list |
|
97 TInt index=iPool.iImplementation->FindTableIndexFromFirstVal(iVal, tableId); |
|
98 return index; |
|
99 } |
|
100 |
|
101 |
|
102 EXPORT_C const TStringTable* RStringBase::OriginalTableRef() const |
|
103 /** Gets the table (if any) that first added the current string to the pool. |
|
104 |
|
105 Note there multiple tables can contain the same string. |
|
106 |
|
107 @return The table or NULL if the string was created dynamically (not from |
|
108 a table) */ |
|
109 { |
|
110 if(StringUtils::IsTableEntry(iVal)) |
|
111 return &iPool.iImplementation->TableRef(iVal); |
|
112 else |
|
113 return NULL; |
|
114 } |
|
115 |
|
116 /** Implementation of RStringPool class*/ |
|
117 |
|
118 EXPORT_C void RStringPool::OpenL() |
|
119 /** Creates an initialised string pool with no pre-loaded string tables. |
|
120 |
|
121 @leave KErrNoMemory Not enough memory to open the pool */ |
|
122 { |
|
123 iImplementation = new (ELeave) CStringPoolImplementation; |
|
124 } |
|
125 |
|
126 EXPORT_C void RStringPool::OpenL(const TStringTable& aTable,MStringPoolCloseCallBack& aCallBack) |
|
127 /** Creates an initialised string pool with a pre-loaded string table, and a string-pool-closing |
|
128 callback. |
|
129 |
|
130 @param aTable The pre-loaded string table. |
|
131 @param aCallBack Callback interface that is called when the string pool closes |
|
132 @leave KErrNoMemory Not enough memory to open the pool */ |
|
133 { |
|
134 if (!iImplementation) |
|
135 { |
|
136 iImplementation = new (ELeave) CStringPoolImplementation; |
|
137 CleanupClosePushL(*this); |
|
138 iImplementation->AddTableL(aTable); |
|
139 iImplementation->AddCallBackL(aCallBack); |
|
140 CleanupStack::Pop(); //this |
|
141 } |
|
142 else |
|
143 { |
|
144 iImplementation->AddTableL(aTable); |
|
145 iImplementation->AddCallBackL(aCallBack); |
|
146 } |
|
147 } |
|
148 |
|
149 EXPORT_C void RStringPool::OpenL(const TStringTable& aTable) |
|
150 /** Creates an initialised string pool with a pre-loaded string table. |
|
151 |
|
152 @param aTable The pre-loaded string table. |
|
153 @leave KErrNoMemory Not enough memory to open the pool */ |
|
154 { |
|
155 if (!iImplementation) |
|
156 { |
|
157 iImplementation = new (ELeave) CStringPoolImplementation; |
|
158 CleanupClosePushL(*this); |
|
159 iImplementation->AddTableL(aTable); |
|
160 CleanupStack::Pop(); //this |
|
161 } |
|
162 else |
|
163 { |
|
164 iImplementation->AddTableL(aTable); |
|
165 } |
|
166 } |
|
167 |
|
168 |
|
169 EXPORT_C void RStringPool::Close() |
|
170 /** Closes the string pool table. |
|
171 |
|
172 This invalidates all other handles to the table. */ |
|
173 { |
|
174 delete iImplementation; |
|
175 iImplementation = NULL; |
|
176 } |
|
177 |
|
178 EXPORT_C RStringF RStringPool::OpenFStringL(const TDesC8& aString) const |
|
179 /** Creates an RStringF using the current string pool. |
|
180 |
|
181 The string is opened as case-insensitive. |
|
182 |
|
183 @param aString The value of the string. |
|
184 @leave KErrNoMemory Not enough memory to open the string |
|
185 @return Initialised RStringF object */ |
|
186 { |
|
187 RStringTokenEither newString = iImplementation->OpenL(aString, ETrue); |
|
188 RStringF r; |
|
189 r.iPool = *this; |
|
190 r.iVal = newString.iVal; |
|
191 return r; |
|
192 } |
|
193 |
|
194 EXPORT_C RString RStringPool::OpenStringL(const TDesC8& aString) const |
|
195 /** Creates an RString using the current string pool. |
|
196 |
|
197 The string is opened as case-sensitive. |
|
198 |
|
199 @param aString The value of the string. |
|
200 @leave KErrNoMemory Not enough memory to open the string |
|
201 @return Initialised RString object */ |
|
202 { |
|
203 RStringTokenEither newString = iImplementation->OpenL(aString, EFalse); |
|
204 RString r; |
|
205 r.iPool = *this; |
|
206 r.iVal = newString.iVal; |
|
207 return r; |
|
208 } |
|
209 |
|
210 EXPORT_C RString RStringPool::String(RStringToken aString) const |
|
211 /** Creates an RString from the supplied RStringToken. |
|
212 |
|
213 @param aString The string token |
|
214 @return Initialised RString object */ |
|
215 { |
|
216 RString r; |
|
217 r.iPool = *this; |
|
218 r.iVal = aString.iVal; |
|
219 return r; |
|
220 } |
|
221 |
|
222 EXPORT_C RString RStringPool::String(TInt aIndex,const TStringTable& aTable) const |
|
223 /** Gets a case-sensitive string specified by a string table enumeration value. |
|
224 |
|
225 aIndex is interpreted as an offset into the handle's pre-loaded string table. |
|
226 |
|
227 @param aIndex The string table enumeration value |
|
228 @param aTable The string table from which to read the string |
|
229 @return Initialised RString object |
|
230 @panic EStringTableNotFound If the table supplied is not found. This panic is raised in debug builds only, in release mode the behaviour is undefined*/ |
|
231 { |
|
232 __ASSERT_DEBUG(aTable.iCaseSensitive==1,StringPoolPanic::Panic(StringPoolPanic::ECreatingStringWithWrongCase)); |
|
233 if(aIndex <(TInt)aTable.iCount) |
|
234 {//the index is in valid range the index |
|
235 RString r; |
|
236 r.iPool = *this; |
|
237 TInt16 tableUid = iImplementation->TableUid(aTable); |
|
238 __ASSERT_DEBUG(tableUid!=KErrNotFound,StringPoolPanic::Panic(StringPoolPanic::EStringTableNotFound)); |
|
239 r.iVal = StringUtils::ValFromIndex(aIndex, tableUid); |
|
240 TInt originalVal; |
|
241 if (KErrNotFound!=(originalVal=iImplementation->FindFirstValFromDuplicate(r.iVal))) |
|
242 { |
|
243 r.iVal=originalVal; |
|
244 } |
|
245 return r; |
|
246 } |
|
247 else // the index is out of range |
|
248 return RString(); |
|
249 } |
|
250 |
|
251 EXPORT_C RStringF RStringPool::StringF(RStringTokenF aString) const |
|
252 /** Creates a RStringF from the supplied RStringToken. |
|
253 |
|
254 @param aString The value of the string |
|
255 @return Initialised RStringF object */ |
|
256 { |
|
257 RStringF r; |
|
258 r.iPool = *this; |
|
259 r.iVal = aString.iVal; |
|
260 return r; |
|
261 } |
|
262 |
|
263 EXPORT_C RStringF RStringPool::StringF(TInt aIndex,const TStringTable& aTable) const |
|
264 /** Gets a case-insensitive string specified by a string table enumeration value. |
|
265 |
|
266 Creates an RStringF from a string table enumeration value. |
|
267 |
|
268 aIndex is interpreted as an offset into the handle's pre-loaded string table. |
|
269 |
|
270 @param aIndex The string table enumeration value |
|
271 @param aTable The string table from which to read the string |
|
272 @return Initialised RStringF object |
|
273 @panic EStringTableNotFound If the table supplied is not found. This panic is raised in debug builds only, in release mode the behaviour is undefined*/ |
|
274 { |
|
275 __ASSERT_DEBUG(aTable.iCaseSensitive==0,StringPoolPanic::Panic(StringPoolPanic::ECreatingStringWithWrongCase)); |
|
276 if(aIndex <(TInt)aTable.iCount) |
|
277 {//the index is in valid range the index |
|
278 RStringF r; |
|
279 r.iPool = *this; |
|
280 TInt16 tableUid = iImplementation->TableUid(aTable); |
|
281 __ASSERT_DEBUG(tableUid!=KErrNotFound,StringPoolPanic::Panic(StringPoolPanic::EStringTableNotFound)); |
|
282 r.iVal = StringUtils::ValFromIndexF(aIndex, tableUid); |
|
283 TInt originalVal; |
|
284 if (KErrNotFound!=(originalVal=iImplementation->FindFirstValFromDuplicate(r.iVal))) |
|
285 { |
|
286 r.iVal=originalVal; |
|
287 } |
|
288 return r; |
|
289 } |
|
290 else // the index is out of range so return an empty string |
|
291 return RStringF(); |
|
292 } |