1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * CINIDATA.CPP |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <e32std.h> |
|
22 #include "iniparser.h" |
|
23 |
|
24 // Default directory to look for INI file |
|
25 _LIT(KIniFileDir,"\\System\\Data\\"); |
|
26 _LIT(KIniSysDrive, "${SYSDRIVE}"); |
|
27 _LIT(KLegacySysDrive, "C:"); |
|
28 |
|
29 // Constant Value changed for defect047130 fix |
|
30 const TInt KTokenSize=256; |
|
31 |
|
32 enum TIniPanic |
|
33 { |
|
34 ESectionNameTooBig, |
|
35 EKeyNameTooBig, |
|
36 }; |
|
37 |
|
38 #ifndef EKA2 |
|
39 //////////////////////////////////////////////////////////////////////////////// |
|
40 // |
|
41 // DLL entry point |
|
42 // |
|
43 GLDEF_C TInt E32Dll(TDllReason /*aReason*/) |
|
44 |
|
45 { |
|
46 return (KErrNone); |
|
47 } |
|
48 #endif |
|
49 |
|
50 //////////////////////////////////////////////////////////////////////////////// |
|
51 void Panic(TIniPanic aPanic) |
|
52 { |
|
53 _LIT(CIniData,"CIniData"); |
|
54 User::Panic(CIniData,aPanic); |
|
55 } |
|
56 |
|
57 /** |
|
58 * Updates ${SYSDRIVE} variables in the ini file buffer |
|
59 * To the system drive set during object constrcution |
|
60 */ |
|
61 void CIniData::UpdateVariablesL() |
|
62 { |
|
63 if (iIniData != NULL) |
|
64 { |
|
65 //prevent re-allocating to copy the same data again |
|
66 TPtr temp(iIniData->Des()) ; |
|
67 if(iPtr.Compare(temp) != 0) |
|
68 { |
|
69 delete iIniData; |
|
70 iIniData = NULL ; |
|
71 } |
|
72 } |
|
73 // if iIniData was never allocated or just deleted... |
|
74 if(iIniData == NULL) |
|
75 { |
|
76 iIniData = iPtr.AllocL(); |
|
77 } |
|
78 |
|
79 iPtrExpandedVars.Set(iIniData->Des()); |
|
80 |
|
81 if(iPtrExpandedVars.FindF(KIniSysDrive) == KErrNotFound) |
|
82 return; |
|
83 |
|
84 while ( iPtrExpandedVars.Find(KIniSysDrive) != KErrNotFound ) |
|
85 { |
|
86 TInt offset = iPtrExpandedVars.Find(KIniSysDrive); |
|
87 iPtrExpandedVars.Replace(offset, 11, iSysDrive); |
|
88 } |
|
89 } |
|
90 |
|
91 /** |
|
92 * Constructor |
|
93 */ |
|
94 EXPORT_C CIniData::CIniData() |
|
95 : iPtr(NULL,0), iPtrExpandedVars(NULL,0) |
|
96 { |
|
97 __DECLARE_NAME(_S("CIniData")); |
|
98 iSysDrive.Copy(KLegacySysDrive); |
|
99 } |
|
100 |
|
101 /** |
|
102 * Overloaded constructor |
|
103 * Takes in the system drive letter to overwrite |
|
104 */ |
|
105 EXPORT_C CIniData::CIniData(const TDesC& aSysDrive) |
|
106 : iPtr(NULL,0), iPtrExpandedVars(NULL,0) |
|
107 { |
|
108 __DECLARE_NAME(_S("CIniData")); |
|
109 if ( aSysDrive.Length() == 2 ) |
|
110 iSysDrive.Copy(aSysDrive); |
|
111 } |
|
112 |
|
113 /** |
|
114 * Destructor |
|
115 * Frees the resources located in second-phase constructor |
|
116 */ |
|
117 EXPORT_C CIniData::~CIniData() |
|
118 { |
|
119 if( iIniData != NULL ) |
|
120 delete iIniData; |
|
121 delete (TText*)iPtr.Ptr(); |
|
122 delete iToken; |
|
123 delete iName; |
|
124 } |
|
125 |
|
126 /** |
|
127 * Creates, and returns a pointer to CIniData object, leave on failure |
|
128 * @param aName - Path and name of the ini file to be parsed |
|
129 * @return A pointer to the CiniData object |
|
130 */ |
|
131 EXPORT_C CIniData* CIniData::NewL(const TDesC& aName) |
|
132 { |
|
133 CIniData* p=new(ELeave) CIniData(); |
|
134 CleanupStack::PushL(p); |
|
135 p->ConstructL(aName); |
|
136 CleanupStack::Pop(); |
|
137 return p; |
|
138 } |
|
139 |
|
140 /** |
|
141 * Creates, and returns a pointer to CIniData object, leave on failure |
|
142 * @param aName - Path and name of the ini file to be parsed |
|
143 * @param aSysDrive - Drive letter to overwrite the default system drive |
|
144 * @return A pointer to the CiniData object |
|
145 */ |
|
146 EXPORT_C CIniData* CIniData::NewL(const TDesC& aName, const TDesC& aSysDrive) |
|
147 { |
|
148 CIniData* p=new(ELeave) CIniData(aSysDrive); |
|
149 CleanupStack::PushL(p); |
|
150 p->ConstructL(aName); |
|
151 CleanupStack::Pop(); |
|
152 return p; |
|
153 } |
|
154 |
|
155 /** |
|
156 * Second-phase constructor. |
|
157 * The function attempts to allocate a buffer and Read file's contents into iPtr |
|
158 * @param aName the name of the file which contains the ini data |
|
159 * @leave One of the system-wide error codes |
|
160 */ |
|
161 EXPORT_C void CIniData::ConstructL(const TDesC& aName) |
|
162 { |
|
163 // Allocate space for token |
|
164 iToken=HBufC::NewL(KTokenSize+2); // 2 extra chars for [tokenName] |
|
165 |
|
166 // Connect to file server |
|
167 TAutoClose<RFs> fs; |
|
168 User::LeaveIfError(fs.iObj.Connect()); |
|
169 fs.PushL(); |
|
170 |
|
171 // Find file, given name |
|
172 TFindFile ff(fs.iObj); |
|
173 TFileName iniFileDir(KLegacySysDrive); |
|
174 iniFileDir.Append(KIniFileDir); |
|
175 User::LeaveIfError(ff.FindByDir(aName, iniFileDir)); |
|
176 iName=ff.File().AllocL(); |
|
177 |
|
178 // Open file |
|
179 TAutoClose<RFile> file; |
|
180 TInt size; |
|
181 User::LeaveIfError(file.iObj.Open(fs.iObj,*iName,EFileStreamText|EFileShareReadersOrWriters)); |
|
182 file.PushL(); |
|
183 |
|
184 // Get file size and read in |
|
185 User::LeaveIfError(file.iObj.Size(size)); |
|
186 TText* data=(TText*)User::AllocL(size); |
|
187 iPtr.Set(data, size/sizeof(TText), size/sizeof(TText)); |
|
188 TPtr8 dest((TUint8*)data, 0, size); |
|
189 User::LeaveIfError(file.iObj.Read(dest)); |
|
190 TUint8* ptr = (TUint8*)data; |
|
191 |
|
192 // |
|
193 // This is orderred as FEFF assuming the processor is Little Endian |
|
194 // The data in the file is FFFE. PRR 28/9/98 |
|
195 // |
|
196 if(size>=(TInt)sizeof(TText) && iPtr[0]==0xFEFF) |
|
197 { |
|
198 // UNICODE Text file so lose the FFFE |
|
199 Mem::Copy(ptr, ptr+sizeof(TText), size-sizeof(TText)); |
|
200 iPtr.Set(data, size/sizeof(TText)-1, size/sizeof(TText)-1); |
|
201 } |
|
202 else if(size) |
|
203 { |
|
204 // NON-UNICODE so convert to UNICODE |
|
205 TText* newdata = (TText*)User::AllocL(size*sizeof(TText)); |
|
206 iPtr.Set(newdata, size, size); |
|
207 TInt i; |
|
208 for(i=0 ; i<size ; ++i) |
|
209 iPtr[i]=ptr[i]; |
|
210 delete data; |
|
211 } |
|
212 |
|
213 // Create a duplicate of the iPtr |
|
214 // Expand all ${SYSDRIVE} entries to system drive letter |
|
215 UpdateVariablesL(); |
|
216 |
|
217 file.Pop(); |
|
218 fs.Pop(); |
|
219 } |
|
220 |
|
221 //////////////////////////////////////////////////////////////////////////////// |
|
222 /** |
|
223 * Find a text value from given aKeyName regardless the section in the ini data file |
|
224 * @param aKeyName Key being searched for |
|
225 * @param aResult On return, contains the text result |
|
226 * @return ETrue if found, otherwise EFalse |
|
227 */ |
|
228 EXPORT_C TBool CIniData::FindVar(const TDesC &aKeyName, TPtrC &aResult) |
|
229 { |
|
230 // Call with no section, so starts at beginning |
|
231 if (FindVar((TDesC&)KNullDesC , aKeyName, aResult)) |
|
232 return(ETrue); |
|
233 else |
|
234 return(EFalse); |
|
235 } |
|
236 |
|
237 /** |
|
238 * Find a text value from given aKeyName and aSecName in the ini data file |
|
239 * @param aSectName Section containing key |
|
240 * @param aKeyName Key being searched for in aSectName |
|
241 * @param aResult On return, contains the text result |
|
242 * @return ETrue if found, otherwise EFalse |
|
243 */ |
|
244 EXPORT_C TBool CIniData::FindVar(const TDesC &aSectName,const TDesC &aKeyName,TPtrC &aResult) |
|
245 { |
|
246 __ASSERT_DEBUG(aSectName.Length()<=KTokenSize,Panic(ESectionNameTooBig)); |
|
247 __ASSERT_DEBUG(aKeyName.Length()<=KTokenSize,Panic(EKeyNameTooBig)); |
|
248 |
|
249 return FindVar(aSectName,aKeyName,aResult, iPtrExpandedVars); |
|
250 } |
|
251 |
|
252 /** |
|
253 * Find a text value from given aKeyName and aSecName in the provided ini data pointer |
|
254 * @param aSectName Section containing key |
|
255 * @param aKeyName Key being searched for in aSectName |
|
256 * @param aResult On return, contains the text result |
|
257 * @param aIniDataPtr ini data pointer to be used to find the value |
|
258 * @return ETrue if found, otherwise EFalse |
|
259 */ |
|
260 TBool CIniData::FindVar(const TDesC &aSectName,const TDesC &aKeyName,TPtrC &aResult, TPtr& aIniDataPtr) |
|
261 { |
|
262 TInt posStartOfSection(0); |
|
263 TInt posEndOfSection(aIniDataPtr.Length()); // Default to the entire length of the ini data |
|
264 TPtrC SearchBuf; |
|
265 |
|
266 // If we have a section, set pos to section start |
|
267 TInt posI(0); // Position in internal data Buffer |
|
268 if( aSectName.Length() > 0 ) |
|
269 { |
|
270 TBool FoundSection(false); |
|
271 while ( ! FoundSection ) |
|
272 { |
|
273 // Move search buffer to next area of interest |
|
274 SearchBuf.Set(aIniDataPtr.Mid(posI)); |
|
275 |
|
276 // Make up token "[SECTIONNAME]", to search for |
|
277 TPtr sectionToken=iToken->Des(); |
|
278 _LIT(sectionTokenFmtString,"[%S]"); |
|
279 sectionToken.Format(sectionTokenFmtString,&aSectName); |
|
280 |
|
281 // Search for next occurrence of aSectName |
|
282 TInt posSB = SearchBuf.Find(sectionToken); |
|
283 |
|
284 if (posSB==KErrNotFound) |
|
285 return(EFalse); |
|
286 |
|
287 // Check this is at beginning of line (ie. non-commented) |
|
288 // ie. Check preceding char was LF |
|
289 if(posSB>0) |
|
290 { |
|
291 // Create a Buffer, starting one char before found subBuf |
|
292 TPtrC CharBefore(SearchBuf.Right(SearchBuf.Length()-posSB+1)); |
|
293 // Check first char is end of prev |
|
294 if(CharBefore[0] == '\n') |
|
295 { |
|
296 FoundSection = ETrue; // found |
|
297 posI = posI + posSB; |
|
298 } |
|
299 else |
|
300 { |
|
301 posI = posI + posSB + 1; // try again |
|
302 } |
|
303 } |
|
304 else |
|
305 { |
|
306 FoundSection = ETrue; |
|
307 } |
|
308 |
|
309 } // while ( ! FoundSection ) |
|
310 |
|
311 // Set start of section, after section name, (incl '[' and ']') |
|
312 posStartOfSection = posI + aSectName.Length() + 2; |
|
313 |
|
314 // Set end of section, by finding begin of next section or end |
|
315 SearchBuf.Set(aIniDataPtr.Mid(posI)); |
|
316 _LIT(nextSectionBuf,"\n["); |
|
317 TInt posSB = SearchBuf.Find(nextSectionBuf); |
|
318 if(posSB != KErrNotFound) |
|
319 { |
|
320 posEndOfSection = posI + posSB; |
|
321 } |
|
322 else |
|
323 { |
|
324 posEndOfSection = aIniDataPtr.Length(); |
|
325 } |
|
326 |
|
327 } // if( aSectName.Length() > 0 ) |
|
328 |
|
329 // Look for key in ini file data Buffer |
|
330 posI = posStartOfSection; |
|
331 TBool FoundKey(false); |
|
332 while ( ! FoundKey ) |
|
333 { |
|
334 // Search for next occurrence of aKeyName |
|
335 SearchBuf.Set(aIniDataPtr.Mid(posI,posEndOfSection-posI)); |
|
336 TInt posSB = SearchBuf.Find(aKeyName); |
|
337 |
|
338 // If not found, return |
|
339 if (posSB==KErrNotFound) |
|
340 return(EFalse); |
|
341 |
|
342 // Check this is at beginning of line (ie. non-commented) |
|
343 // ie. Check preceding char was CR or LF |
|
344 if(posSB>0) |
|
345 { |
|
346 // Create a Buffer, starting one char before found subBuf |
|
347 TPtrC CharBefore(SearchBuf.Right(SearchBuf.Length()-posSB+1)); |
|
348 // Check if the first char is end of prev and also check |
|
349 // if the token found is not a substring of another string |
|
350 TBool beginningOK = ((CharBefore[0] == '\n') || (CharBefore[0] == ' ') || (CharBefore[0] == '\t')); |
|
351 TBool endingOK = ((CharBefore[aKeyName.Length()+1] == '=') || (CharBefore[aKeyName.Length()+1] == ' ') || (CharBefore[aKeyName.Length()+1] == '\t')); |
|
352 if (beginningOK && endingOK) |
|
353 { |
|
354 FoundKey = ETrue; |
|
355 posI = posI + posSB; |
|
356 } |
|
357 else |
|
358 { |
|
359 posI = posI + posSB + 1; |
|
360 } |
|
361 } |
|
362 else |
|
363 { |
|
364 FoundKey = ETrue; |
|
365 } |
|
366 } // while ( ! FoundKey ) |
|
367 |
|
368 // Set pos, to just after '=' sign |
|
369 SearchBuf.Set(aIniDataPtr.Mid(posI)); |
|
370 TInt posSB = SearchBuf.Locate('='); |
|
371 if(posSB==KErrNotFound) // Illegal format, should flag this... |
|
372 return(EFalse); |
|
373 |
|
374 // Identify start and end of data (EOL or EOF) |
|
375 posI = posI + posSB + 1; // 1 char after '=' |
|
376 TInt posValStart = posI; |
|
377 TInt posValEnd; |
|
378 SearchBuf.Set(aIniDataPtr.Mid(posI)); |
|
379 posSB = SearchBuf.Locate('\n'); |
|
380 if(posSB!=KErrNotFound) |
|
381 { |
|
382 // ini file uses LF for EOL |
|
383 posValEnd = posI + posSB; |
|
384 } |
|
385 else |
|
386 { |
|
387 posValEnd = aIniDataPtr.Length(); |
|
388 } |
|
389 |
|
390 // Check we are still in the section requested |
|
391 if( aSectName.Length() > 0 ) |
|
392 { |
|
393 if( posValEnd > posEndOfSection ) |
|
394 { |
|
395 return(EFalse); |
|
396 } |
|
397 } |
|
398 // Parse Buffer from posn of key |
|
399 // Start one space after '=' |
|
400 TLex lex(aIniDataPtr.Mid(posValStart, posValEnd-posValStart)); |
|
401 lex.SkipSpaceAndMark(); // Should be at the start of the data |
|
402 aResult.Set(lex.MarkedToken().Ptr(),posValEnd-posValStart - lex.Offset() ); |
|
403 |
|
404 TInt filterOffset; |
|
405 |
|
406 // Mark the offset value to the end of the value string |
|
407 filterOffset = aResult.Length() - 1; |
|
408 |
|
409 // Loop from end of the value string marked by the offset fetched by above process |
|
410 // And check to see if there is spaces, tabs or carriage returns |
|
411 while(filterOffset >= 0 && |
|
412 (aResult[filterOffset] == '\t' || |
|
413 aResult[filterOffset] == ' ' || |
|
414 aResult[filterOffset] == '\r')) |
|
415 { |
|
416 // If found, reduce the offset by 1 for every space and tab during the while loop |
|
417 filterOffset--; |
|
418 } |
|
419 |
|
420 // The final offset value indicating end of actual value |
|
421 // within the ini data is set to the result string reference passed in |
|
422 aResult.Set(aResult.Mid(0,filterOffset + 1)); |
|
423 |
|
424 return(ETrue); |
|
425 } |
|
426 |
|
427 /** |
|
428 * Find an integer value from given aKeyName regardless the section in the ini data file |
|
429 * @param aKeyName Key being searched for |
|
430 * @param aResult On return, contains the TInt result |
|
431 * @return ETrue if found, otherwise EFalse |
|
432 */ |
|
433 EXPORT_C TBool CIniData::FindVar(const TDesC &aKeyName, TInt &aResult) |
|
434 { |
|
435 TPtrC ptr(NULL,0); |
|
436 if (FindVar(aKeyName,ptr)) |
|
437 { |
|
438 TLex lex(ptr); |
|
439 if (lex.Val(aResult)==KErrNone) |
|
440 return(ETrue); |
|
441 } |
|
442 return(EFalse); |
|
443 } |
|
444 |
|
445 /** |
|
446 * Find an integer value from given aKeyName and aSecName in the ini data file |
|
447 * @param aSectName Section containing key |
|
448 * @param aKeyName Key being searched for in aSectName |
|
449 * @param aResult On return, contains TInt result |
|
450 * @return ETrue if found, otherwise EFalse |
|
451 */ |
|
452 EXPORT_C TBool CIniData::FindVar(const TDesC &aSection,const TDesC &aKeyName,TInt &aResult) |
|
453 { |
|
454 TPtrC ptr(NULL,0); |
|
455 if (FindVar(aSection,aKeyName,ptr)) |
|
456 { |
|
457 TLex lex(ptr); |
|
458 if (lex.Val(aResult)==KErrNone) |
|
459 return(ETrue); |
|
460 } |
|
461 return(EFalse); |
|
462 } |
|
463 /** |
|
464 * Find an 64-bit integer value from given aKeyName and aSecName in the ini data file |
|
465 * @param aSectName Section containing key |
|
466 * @param aKeyName Key being searched for in aSectName |
|
467 * @param aResult On return, contains TInt64 result |
|
468 * @return ETrue if found, otherwise EFalse |
|
469 */ |
|
470 EXPORT_C TBool CIniData::FindVar(const TDesC &aSection, // Section to look under |
|
471 const TDesC &aKeyName, // Key to look for |
|
472 TInt64 &aResult) // Int64 ref to store result |
|
473 { |
|
474 TPtrC ptr(NULL,0); |
|
475 if (FindVar(aSection,aKeyName,ptr)) |
|
476 { |
|
477 TLex lex(ptr); |
|
478 if (lex.Val(aResult)==KErrNone) |
|
479 return(ETrue); |
|
480 } |
|
481 return(EFalse); |
|
482 } |
|
483 /** |
|
484 * Set a text value to given aKeyName and aSecName in the ini data file |
|
485 * @param aSectName Section containing key |
|
486 * @param aKeyName Key being set in aSectName |
|
487 * @param aValue A text value set for the aKeyName in section ASecName |
|
488 * @return KErrNone if sucessful, otherwise system error |
|
489 */ |
|
490 EXPORT_C TInt CIniData::SetValue(const TDesC& aSection,const TDesC& aKeyName,const TDesC& aValue) |
|
491 { |
|
492 // First find the variable - this gives us a descriptor into the |
|
493 // ini data giving the bound of the item that has got to be replaced. |
|
494 TPtrC ptr; |
|
495 |
|
496 if (!FindVar(aSection, aKeyName, ptr, iPtr)) |
|
497 return KErrNotFound; |
|
498 |
|
499 TInt pos = ptr.Ptr()-iPtr.Ptr(); |
|
500 TInt size = iPtr.Length()+aValue.Length()-ptr.Length(); |
|
501 |
|
502 if (size>iPtr.MaxLength()) |
|
503 { |
|
504 size = size * sizeof(TText); |
|
505 TText* newdata = (TText*)User::ReAlloc((TUint8*)iPtr.Ptr(), size); |
|
506 if (newdata == 0) |
|
507 return KErrNoMemory; |
|
508 |
|
509 iPtr.Set(newdata, iPtr.Length(), iPtr.Length()>size/(TInt)sizeof(TText)?iPtr.Length():size/(TInt)sizeof(TText)); |
|
510 } |
|
511 iPtr.Replace(pos, ptr.Length(), aValue); |
|
512 return(KErrNone); |
|
513 } |
|
514 |
|
515 /** |
|
516 * Set a text value to given aKeyName regardless of the section in the ini data file |
|
517 * @param aKeyName Key being searched for |
|
518 * @param aValue A text value set for the aKeyName |
|
519 * @return KErrNone if sucessful, otherwise system error |
|
520 */ |
|
521 EXPORT_C TInt CIniData::SetValue(const TDesC& aKeyName,const TDesC& aValue) |
|
522 { |
|
523 // Call with no section, so starts at beginning |
|
524 return SetValue((TDesC&)KNullDesC, aKeyName, aValue); |
|
525 } |
|
526 |
|
527 /** |
|
528 * Add key aKeyName to end of ini data file |
|
529 * @param aKeyName aKeyName Key being added |
|
530 * @param aValue Text value assigned to the aKeyName |
|
531 * @return KErrNone if sucessful, otherwise system error |
|
532 */ |
|
533 EXPORT_C TInt CIniData::AddValue(const TDesC& aKeyName,const TDesC& aValue) |
|
534 { |
|
535 // Call with no section, so starts at beginning |
|
536 return AddValue((TDesC&)KNullDesC, aKeyName, aValue); |
|
537 } |
|
538 |
|
539 /** |
|
540 * Add key aKeyName to section aSectName |
|
541 * @param aSectName Section |
|
542 * @param aKeyName Key being added to section aSectName |
|
543 * @param aValue A text value added to the aKeyName |
|
544 * @return KErrNone if sucessful, otherwise system error |
|
545 */ |
|
546 EXPORT_C TInt CIniData::AddValue(const TDesC& aSectName,const TDesC& aKeyName,const TDesC& aValue) |
|
547 { |
|
548 // The request will be denied if the variable exists. |
|
549 // |
|
550 // If the variable is not there then making an implementation. |
|
551 // If the Section name existed in the ini file then just append it |
|
552 // to this section otherwise append the section, key name and |
|
553 // variable at the end of the ini file. |
|
554 TPtrC ptr; |
|
555 |
|
556 if (FindVar(aSectName, aKeyName, ptr)) |
|
557 return KErrAlreadyExists; // an key name exists, |
|
558 // not allow to add value again to same key |
|
559 ///////////////////////////// |
|
560 TPtr insertSection =iToken->Des(); |
|
561 TInt size; |
|
562 |
|
563 TInt posEndOfSection(iPtr.Length()); // Default to the entire length of the ini data |
|
564 TPtrC SearchBuf; |
|
565 |
|
566 // If there is a section, set pos to section start |
|
567 TInt posI(0); // Initiate to 0. Position in internal data Buffer |
|
568 TInt posSB(0); |
|
569 if( aSectName.Length() > 0 ) |
|
570 { |
|
571 TBool FoundSection(false); |
|
572 while ( ! FoundSection ) |
|
573 { |
|
574 // Move search buffer to next area of interest |
|
575 SearchBuf.Set(iPtr.Mid(posI)); |
|
576 |
|
577 // Make up token "[SECTIONNAME]", to search for |
|
578 TPtr sectionToken=iToken->Des(); |
|
579 _LIT(sectionTokenFmtString,"[%S]"); |
|
580 sectionToken.Format(sectionTokenFmtString,&aSectName); |
|
581 |
|
582 // Search for next occurrence of aSectName |
|
583 posSB = SearchBuf.Find(sectionToken); |
|
584 |
|
585 // If not found, return |
|
586 if (posSB==KErrNotFound) |
|
587 { |
|
588 FoundSection = ETrue; //Stop while searching |
|
589 _LIT(insertSectionfmt,"\r\n[%S]\r\n%S = %S\r\n"); //if there is no section existed |
|
590 insertSection.Format(insertSectionfmt,&aSectName,&aKeyName, &aValue); |
|
591 } |
|
592 |
|
593 |
|
594 // Check this is at beginning of line (ie. non-commented) |
|
595 // ie. Check preceding char was LF |
|
596 if(posSB>=0) |
|
597 { |
|
598 // Create a Buffer, starting one char before found subBuf |
|
599 TPtrC CharBefore(SearchBuf.Right(SearchBuf.Length()-posSB+1)); |
|
600 // Check first char is end of prev |
|
601 if(CharBefore[0] == '\n' or posSB == 0) |
|
602 { |
|
603 FoundSection = ETrue; // found |
|
604 posI = posI + posSB; |
|
605 _LIT(insertSectionfmt,"\r\n%S = %S\r\n"); //if there is no section existed |
|
606 insertSection.Format(insertSectionfmt,&aKeyName, &aValue); |
|
607 } |
|
608 else |
|
609 { |
|
610 posI = posI + posSB + 1; // try again |
|
611 } |
|
612 } |
|
613 else |
|
614 { |
|
615 FoundSection = ETrue; //found at the beginning of the search buffer |
|
616 } |
|
617 |
|
618 } // while ( ! FoundSection ) |
|
619 |
|
620 // Set start of section, after section name, (incl '[' and ']') |
|
621 if(posSB!=KErrNotFound) |
|
622 { |
|
623 |
|
624 // Set end of section, by finding begin of next section or end |
|
625 SearchBuf.Set(iPtr.Mid(posI)); |
|
626 _LIT(nextSectionBuf,"\n["); |
|
627 TInt posSB = SearchBuf.Find(nextSectionBuf); |
|
628 if(posSB != KErrNotFound) |
|
629 { |
|
630 posEndOfSection = posI + posSB+1; //insert it between \n and [ |
|
631 } |
|
632 else |
|
633 { |
|
634 posEndOfSection = iPtr.Length(); |
|
635 } |
|
636 } |
|
637 |
|
638 } // if( aSectName.Length() > 0 ) |
|
639 |
|
640 // append/insert here |
|
641 size = (iPtr.Length()+ insertSection.Length())*sizeof(TText); |
|
642 if (size>iPtr.MaxLength()) |
|
643 { |
|
644 TText* newdata = (TText*)User::ReAlloc((TUint8*)iPtr.Ptr(), size); |
|
645 if (newdata == 0) |
|
646 return KErrNoMemory; |
|
647 |
|
648 iPtr.Set(newdata, iPtr.Length(), size/(TInt)sizeof(TText)); |
|
649 } |
|
650 |
|
651 iPtr.Insert(posEndOfSection,insertSection); |
|
652 return(KErrNone); |
|
653 } |
|
654 |
|
655 |
|
656 /** |
|
657 * A method used to flush the data in the buffer to the file given in second-phase constructor |
|
658 */ |
|
659 EXPORT_C void CIniData::WriteToFileL() |
|
660 { |
|
661 |
|
662 #ifndef __WINC__ |
|
663 |
|
664 TAutoClose<RFs> fs; |
|
665 User::LeaveIfError(fs.iObj.Connect()); |
|
666 fs.PushL(); |
|
667 |
|
668 TAutoClose<RFile> file; |
|
669 User::LeaveIfError(file.iObj.Replace(fs.iObj,*iName,EFileStreamText|EFileShareExclusive)); |
|
670 file.PushL(); |
|
671 |
|
672 // convert 16 bits to 8 bits stream |
|
673 |
|
674 HBufC8* buf8 = HBufC8::NewL(iPtr.Length()); |
|
675 TPtr8 ptr8(buf8->Des()); |
|
676 ptr8.Copy(iPtr); |
|
677 User::LeaveIfError(file.iObj.Write(ptr8)); |
|
678 |
|
679 delete buf8; |
|
680 |
|
681 // Refresh the iPtrExpandedVars with the new written ini file content |
|
682 // Repeat the process of expanding the ${SYSDRIVE} |
|
683 UpdateVariablesL(); |
|
684 |
|
685 file.Pop(); |
|
686 fs.Pop(); |
|
687 #endif |
|
688 } |
|