fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / tools / source / generic / config.cxx
blob257721eaa4b96b437ed0a5124fb2f066496bc96c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cstddef>
21 #include <cstdlib>
22 #include <limits>
23 #include <new>
24 #include <string.h>
26 #ifdef WNT
27 #include "stdlib.h"
28 #endif
30 #include <osl/file.hxx>
31 #include <tools/stream.hxx>
32 #include <tools/config.hxx>
33 #include <osl/security.h>
34 #include <rtl/strbuf.hxx>
35 #include <sal/log.hxx>
37 struct ImplKeyData
39 ImplKeyData* mpNext;
40 OString maKey;
41 OString maValue;
42 bool mbIsComment;
45 struct ImplGroupData
47 ImplGroupData* mpNext;
48 ImplKeyData* mpFirstKey;
49 OString maGroupName;
50 sal_uInt16 mnEmptyLines;
53 struct ImplConfigData
55 ImplGroupData* mpFirstGroup;
56 OUString maFileName;
57 sal_uIntPtr mnDataUpdateId;
58 sal_uIntPtr mnTimeStamp;
59 LineEnd meLineEnd;
60 sal_uInt16 mnRefCount;
61 bool mbModified;
62 bool mbRead;
63 bool mbIsUTF8BOM;
66 static OUString toUncPath( const OUString& rPath )
68 OUString aFileURL;
70 // check if rFileName is already a URL; if not make it so
71 if( rPath.startsWith( "file://"))
73 aFileURL = rPath;
75 else if( ::osl::FileBase::getFileURLFromSystemPath( rPath, aFileURL ) != ::osl::FileBase::E_None )
77 aFileURL = rPath;
79 return aFileURL;
82 static sal_uIntPtr ImplSysGetConfigTimeStamp( const OUString& rFileName )
84 sal_uIntPtr nTimeStamp = 0;
85 ::osl::DirectoryItem aItem;
86 ::osl::FileStatus aStatus( osl_FileStatus_Mask_ModifyTime );
88 if( ::osl::DirectoryItem::get( rFileName, aItem ) == ::osl::FileBase::E_None &&
89 aItem.getFileStatus( aStatus ) == ::osl::FileBase::E_None )
91 nTimeStamp = aStatus.getModifyTime().Seconds;
94 return nTimeStamp;
97 static sal_uInt8* ImplSysReadConfig( const OUString& rFileName,
98 sal_uInt64& rRead, bool& rbRead, bool& rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
100 sal_uInt8* pBuf = NULL;
101 ::osl::File aFile( rFileName );
103 if( aFile.open( osl_File_OpenFlag_Read ) == ::osl::FileBase::E_None )
105 sal_uInt64 nPos = 0;
106 if( aFile.getSize( nPos ) == ::osl::FileBase::E_None )
108 if (nPos > SAL_MAX_SIZE) {
109 aFile.close();
110 return 0;
112 pBuf = new sal_uInt8[static_cast< std::size_t >(nPos)];
113 sal_uInt64 nRead = 0;
114 if( aFile.read( pBuf, nPos, nRead ) == ::osl::FileBase::E_None && nRead == nPos )
116 //skip the byte-order-mark 0xEF 0xBB 0xBF, if it was UTF8 files
117 unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
118 if (nRead > 2 && memcmp(pBuf, BOM, 3) == 0)
120 nRead -= 3;
121 memmove(pBuf, pBuf + 3, sal::static_int_cast<sal_Size>(nRead * sizeof(sal_uInt8)) );
122 rbIsUTF8BOM = true;
125 rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
126 rbRead = true;
127 rRead = nRead;
129 else
131 delete[] pBuf;
132 pBuf = NULL;
135 aFile.close();
138 return pBuf;
141 static bool ImplSysWriteConfig( const OUString& rFileName,
142 const sal_uInt8* pBuf, sal_uIntPtr nBufLen, bool rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
144 bool bSuccess = false;
145 bool bUTF8BOMSuccess = false;
147 ::osl::File aFile( rFileName );
148 ::osl::FileBase::RC eError = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
149 if( eError != ::osl::FileBase::E_None )
150 eError = aFile.open( osl_File_OpenFlag_Write );
151 if( eError == ::osl::FileBase::E_None )
153 // truncate
154 aFile.setSize( 0 );
155 sal_uInt64 nWritten;
157 //write the byte-order-mark 0xEF 0xBB 0xBF first , if it was UTF8 files
158 if ( rbIsUTF8BOM )
160 unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
161 sal_uInt64 nUTF8BOMWritten;
162 if( aFile.write( BOM, 3, nUTF8BOMWritten ) == ::osl::FileBase::E_None && 3 == nUTF8BOMWritten )
164 bUTF8BOMSuccess = true;
168 if( aFile.write( pBuf, nBufLen, nWritten ) == ::osl::FileBase::E_None && nWritten == nBufLen )
170 bSuccess = true;
172 if ( rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess )
174 rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
178 return rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess;
181 namespace {
182 OString makeOString(const sal_uInt8* p, sal_uInt64 n)
184 if (n > SAL_MAX_INT32)
186 #ifdef WNT
187 abort();
188 #else
189 ::std::abort(); //TODO: handle this gracefully
190 #endif
192 return OString(
193 reinterpret_cast< char const * >(p),
194 sal::static_int_cast< sal_Int32 >(n));
198 static void ImplMakeConfigList( ImplConfigData* pData,
199 const sal_uInt8* pBuf, sal_uInt64 nLen )
201 if ( !nLen )
202 return;
204 // Parse buffer and build config list
205 sal_uInt64 nStart;
206 sal_uInt64 nLineLen;
207 sal_uInt64 nNameLen;
208 sal_uInt64 nKeyLen;
209 sal_uInt64 i;
210 const sal_uInt8* pLine;
211 ImplKeyData* pPrevKey = NULL;
212 ImplKeyData* pKey;
213 ImplGroupData* pPrevGroup = NULL;
214 ImplGroupData* pGroup = NULL;
215 i = 0;
216 while ( i < nLen )
218 // Ctrl+Z
219 if ( pBuf[i] == 0x1A )
220 break;
222 // Remove spaces and tabs
223 while ( (pBuf[i] == ' ') || (pBuf[i] == '\t') )
224 i++;
226 // remember line-starts
227 nStart = i;
228 pLine = pBuf+i;
230 // search line-endings
231 while ( (i < nLen) && pBuf[i] && (pBuf[i] != '\r') && (pBuf[i] != '\n') &&
232 (pBuf[i] != 0x1A) )
233 i++;
235 nLineLen = i-nStart;
237 // if Line-ending is found, continue once
238 if ( (i+1 < nLen) &&
239 (pBuf[i] != pBuf[i+1]) &&
240 ((pBuf[i+1] == '\r') || (pBuf[i+1] == '\n')) )
241 i++;
242 i++;
244 // evaluate line
245 if ( *pLine == '[' )
247 pGroup = new ImplGroupData;
248 pGroup->mpNext = NULL;
249 pGroup->mpFirstKey = NULL;
250 pGroup->mnEmptyLines = 0;
251 if ( pPrevGroup )
252 pPrevGroup->mpNext = pGroup;
253 else
254 pData->mpFirstGroup = pGroup;
255 pPrevGroup = pGroup;
256 pPrevKey = NULL;
257 pKey = NULL;
259 // filter group names
260 pLine++;
261 nLineLen--;
262 // remove spaces and tabs
263 while ( (*pLine == ' ') || (*pLine == '\t') )
265 nLineLen--;
266 pLine++;
268 nNameLen = 0;
269 while ( (nNameLen < nLineLen) && (pLine[nNameLen] != ']') )
270 nNameLen++;
271 if ( nNameLen )
273 while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
274 nNameLen--;
276 pGroup->maGroupName = makeOString(pLine, nNameLen);
278 else
280 if ( nLineLen )
282 // If no group exists yet, add to default
283 if ( !pGroup )
285 pGroup = new ImplGroupData;
286 pGroup->mpNext = NULL;
287 pGroup->mpFirstKey = NULL;
288 pGroup->mnEmptyLines = 0;
289 pData->mpFirstGroup = pGroup;
290 pPrevGroup = pGroup;
291 pPrevKey = NULL;
294 // if empty line, append it
295 if ( pPrevKey )
297 while ( pGroup->mnEmptyLines )
299 pKey = new ImplKeyData;
300 pKey->mbIsComment = true;
301 pPrevKey->mpNext = pKey;
302 pPrevKey = pKey;
303 pGroup->mnEmptyLines--;
307 // Generate new key
308 pKey = new ImplKeyData;
309 pKey->mpNext = NULL;
310 if ( pPrevKey )
311 pPrevKey->mpNext = pKey;
312 else
313 pGroup->mpFirstKey = pKey;
314 pPrevKey = pKey;
315 if ( pLine[0] == ';' )
317 pKey->maValue = makeOString(pLine, nLineLen);
318 pKey->mbIsComment = true;
320 else
322 pKey->mbIsComment = false;
323 nNameLen = 0;
324 while ( (nNameLen < nLineLen) && (pLine[nNameLen] != '=') )
325 nNameLen++;
326 nKeyLen = nNameLen;
327 // Remove spaces and tabs
328 if ( nNameLen )
330 while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
331 nNameLen--;
333 pKey->maKey = makeOString(pLine, nNameLen);
334 nKeyLen++;
335 if ( nKeyLen < nLineLen )
337 pLine += nKeyLen;
338 nLineLen -= nKeyLen;
339 // Remove spaces and tabs
340 while ( (*pLine == ' ') || (*pLine == '\t') )
342 nLineLen--;
343 pLine++;
345 if ( nLineLen )
347 while ( (pLine[nLineLen-1] == ' ') || (pLine[nLineLen-1] == '\t') )
348 nLineLen--;
349 pKey->maValue = makeOString(pLine, nLineLen);
354 else
356 // Spaces are counted and appended only after key generation,
357 // as we want to store spaces even after adding new keys
358 if ( pGroup )
359 pGroup->mnEmptyLines++;
365 static sal_uInt8* ImplGetConfigBuffer( const ImplConfigData* pData, sal_uIntPtr& rLen )
367 sal_uInt8* pWriteBuf;
368 sal_uInt8* pBuf;
369 sal_uInt8 aLineEndBuf[2] = {0, 0};
370 ImplKeyData* pKey;
371 ImplGroupData* pGroup;
372 unsigned int nBufLen;
373 sal_uInt32 nValueLen;
374 sal_uInt32 nKeyLen;
375 sal_uInt32 nLineEndLen;
377 if ( pData->meLineEnd == LINEEND_CR )
379 aLineEndBuf[0] = '\r';
380 nLineEndLen = 1;
382 else if ( pData->meLineEnd == LINEEND_LF )
384 aLineEndBuf[0] = '\n';
385 nLineEndLen = 1;
387 else
389 aLineEndBuf[0] = '\r';
390 aLineEndBuf[1] = '\n';
391 nLineEndLen = 2;
394 nBufLen = 0;
395 pGroup = pData->mpFirstGroup;
396 while ( pGroup )
398 // Don't write empty groups
399 if ( pGroup->mpFirstKey )
401 nBufLen += pGroup->maGroupName.getLength() + nLineEndLen + 2;
402 pKey = pGroup->mpFirstKey;
403 while ( pKey )
405 nValueLen = pKey->maValue.getLength();
406 if ( pKey->mbIsComment )
407 nBufLen += nValueLen + nLineEndLen;
408 else
409 nBufLen += pKey->maKey.getLength() + nValueLen + nLineEndLen + 1;
411 pKey = pKey->mpNext;
414 // Write empty lines after each group
415 if ( !pGroup->mnEmptyLines )
416 pGroup->mnEmptyLines = 1;
417 nBufLen += nLineEndLen * pGroup->mnEmptyLines;
420 pGroup = pGroup->mpNext;
423 // Output buffer length
424 rLen = nBufLen;
425 if ( !nBufLen )
427 pWriteBuf = new sal_uInt8[nLineEndLen];
428 if ( pWriteBuf )
430 pWriteBuf[0] = aLineEndBuf[0];
431 if ( nLineEndLen == 2 )
432 pWriteBuf[1] = aLineEndBuf[1];
433 return pWriteBuf;
435 else
436 return 0;
439 // Allocate new write buffer (caller frees it)
440 pWriteBuf = new sal_uInt8[nBufLen];
441 if ( !pWriteBuf )
442 return 0;
444 // fill buffer
445 pBuf = pWriteBuf;
446 pGroup = pData->mpFirstGroup;
447 while ( pGroup )
449 // Don't write empty groups
450 if ( pGroup->mpFirstKey )
452 *pBuf = '['; pBuf++;
453 memcpy( pBuf, pGroup->maGroupName.getStr(), pGroup->maGroupName.getLength() );
454 pBuf += pGroup->maGroupName.getLength();
455 *pBuf = ']'; pBuf++;
456 *pBuf = aLineEndBuf[0]; pBuf++;
457 if ( nLineEndLen == 2 )
459 *pBuf = aLineEndBuf[1]; pBuf++;
461 pKey = pGroup->mpFirstKey;
462 while ( pKey )
464 nValueLen = pKey->maValue.getLength();
465 if ( pKey->mbIsComment )
467 if ( nValueLen )
469 memcpy( pBuf, pKey->maValue.getStr(), nValueLen );
470 pBuf += nValueLen;
472 *pBuf = aLineEndBuf[0]; pBuf++;
473 if ( nLineEndLen == 2 )
475 *pBuf = aLineEndBuf[1]; pBuf++;
478 else
480 nKeyLen = pKey->maKey.getLength();
481 memcpy( pBuf, pKey->maKey.getStr(), nKeyLen );
482 pBuf += nKeyLen;
483 *pBuf = '='; pBuf++;
484 memcpy( pBuf, pKey->maValue.getStr(), nValueLen );
485 pBuf += nValueLen;
486 *pBuf = aLineEndBuf[0]; pBuf++;
487 if ( nLineEndLen == 2 )
489 *pBuf = aLineEndBuf[1]; pBuf++;
493 pKey = pKey->mpNext;
496 // Store empty line after each group
497 sal_uInt16 nEmptyLines = pGroup->mnEmptyLines;
498 while ( nEmptyLines )
500 *pBuf = aLineEndBuf[0]; pBuf++;
501 if ( nLineEndLen == 2 )
503 *pBuf = aLineEndBuf[1]; pBuf++;
505 nEmptyLines--;
509 pGroup = pGroup->mpNext;
512 return pWriteBuf;
515 static void ImplReadConfig( ImplConfigData* pData )
517 sal_uIntPtr nTimeStamp = 0;
518 sal_uInt64 nRead = 0;
519 bool bRead = false;
520 bool bIsUTF8BOM = false;
521 sal_uInt8* pBuf = ImplSysReadConfig( pData->maFileName, nRead, bRead, bIsUTF8BOM, nTimeStamp );
523 // Read config list from buffer
524 if ( pBuf )
526 ImplMakeConfigList( pData, pBuf, nRead );
527 delete[] pBuf;
529 pData->mnTimeStamp = nTimeStamp;
530 pData->mbModified = false;
531 if ( bRead )
532 pData->mbRead = true;
533 if ( bIsUTF8BOM )
534 pData->mbIsUTF8BOM = true;
537 static void ImplWriteConfig( ImplConfigData* pData )
539 SAL_WARN_IF( pData->mnTimeStamp != ImplSysGetConfigTimeStamp( pData->maFileName ),
540 "tools.generic", "Config overwrites modified configfile: " << pData->maFileName );
542 // Read config list from buffer
543 sal_uIntPtr nBufLen;
544 sal_uInt8* pBuf = ImplGetConfigBuffer( pData, nBufLen );
545 if ( pBuf )
547 if ( ImplSysWriteConfig( pData->maFileName, pBuf, nBufLen, pData->mbIsUTF8BOM, pData->mnTimeStamp ) )
548 pData->mbModified = false;
549 delete[] pBuf;
551 else
552 pData->mbModified = false;
555 static void ImplDeleteConfigData( ImplConfigData* pData )
557 ImplKeyData* pTempKey;
558 ImplKeyData* pKey;
559 ImplGroupData* pTempGroup;
560 ImplGroupData* pGroup = pData->mpFirstGroup;
561 while ( pGroup )
563 pTempGroup = pGroup->mpNext;
565 // remove all keys
566 pKey = pGroup->mpFirstKey;
567 while ( pKey )
569 pTempKey = pKey->mpNext;
570 delete pKey;
571 pKey = pTempKey;
574 // remove group and continue
575 delete pGroup;
576 pGroup = pTempGroup;
579 pData->mpFirstGroup = NULL;
582 static ImplConfigData* ImplGetConfigData( const OUString& rFileName )
584 ImplConfigData* pData;
586 pData = new ImplConfigData;
587 pData->maFileName = rFileName;
588 pData->mpFirstGroup = NULL;
589 pData->mnDataUpdateId = 0;
590 pData->meLineEnd = LINEEND_CRLF;
591 pData->mnRefCount = 0;
592 pData->mbRead = false;
593 pData->mbIsUTF8BOM = false;
594 ImplReadConfig( pData );
596 return pData;
599 static void ImplFreeConfigData( ImplConfigData* pDelData )
601 ImplDeleteConfigData( pDelData );
602 delete pDelData;
605 bool Config::ImplUpdateConfig() const
607 // Re-read file if timestamp differs
608 if ( mpData->mnTimeStamp != ImplSysGetConfigTimeStamp( maFileName ) )
610 ImplDeleteConfigData( mpData );
611 ImplReadConfig( mpData );
612 mpData->mnDataUpdateId++;
613 return true;
615 else
616 return false;
619 ImplGroupData* Config::ImplGetGroup() const
621 if ( !mpActGroup || (mnDataUpdateId != mpData->mnDataUpdateId) )
623 ImplGroupData* pPrevGroup = NULL;
624 ImplGroupData* pGroup = mpData->mpFirstGroup;
625 while ( pGroup )
627 if ( pGroup->maGroupName.equalsIgnoreAsciiCase(maGroupName) )
628 break;
630 pPrevGroup = pGroup;
631 pGroup = pGroup->mpNext;
634 // Add group if not exists
635 if ( !pGroup )
637 pGroup = new ImplGroupData;
638 pGroup->mpNext = NULL;
639 pGroup->mpFirstKey = NULL;
640 pGroup->mnEmptyLines = 1;
641 if ( pPrevGroup )
642 pPrevGroup->mpNext = pGroup;
643 else
644 mpData->mpFirstGroup = pGroup;
647 // Always inherit group names and upate cache members
648 pGroup->maGroupName = maGroupName;
649 const_cast<Config*>(this)->mnDataUpdateId = mpData->mnDataUpdateId;
650 const_cast<Config*>(this)->mpActGroup = pGroup;
653 return mpActGroup;
656 Config::Config( const OUString& rFileName )
658 // Initialize config data
659 maFileName = toUncPath( rFileName );
660 mpData = ImplGetConfigData( maFileName );
661 mpActGroup = NULL;
662 mnDataUpdateId = 0;
663 mnLockCount = 1;
664 mbPersistence = true;
666 #ifdef DBG_UTIL
667 OStringBuffer aTraceStr("Config::Config( ");
668 aTraceStr.append(OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
669 aTraceStr.append(" )");
670 OSL_TRACE("%s", aTraceStr.getStr());
671 #endif
674 Config::~Config()
676 #ifdef DBG_UTIL
677 OSL_TRACE( "Config::~Config()" );
678 #endif
680 Flush();
681 ImplFreeConfigData( mpData );
684 void Config::SetGroup(const OString& rGroup)
686 // If group is to be reset, it needs to be updated on next call
687 if ( maGroupName != rGroup )
689 maGroupName = rGroup;
690 mnDataUpdateId = mpData->mnDataUpdateId-1;
694 void Config::DeleteGroup(const OString& rGroup)
696 // Update config data if necessary
697 if ( !mnLockCount || !mpData->mbRead )
699 ImplUpdateConfig();
700 mpData->mbRead = true;
703 ImplGroupData* pPrevGroup = NULL;
704 ImplGroupData* pGroup = mpData->mpFirstGroup;
705 while ( pGroup )
707 if ( pGroup->maGroupName.equalsIgnoreAsciiCase(rGroup) )
708 break;
710 pPrevGroup = pGroup;
711 pGroup = pGroup->mpNext;
714 if ( pGroup )
716 // Remove all keys
717 ImplKeyData* pTempKey;
718 ImplKeyData* pKey = pGroup->mpFirstKey;
719 while ( pKey )
721 pTempKey = pKey->mpNext;
722 delete pKey;
723 pKey = pTempKey;
726 // Rewire pointers and remove group
727 if ( pPrevGroup )
728 pPrevGroup->mpNext = pGroup->mpNext;
729 else
730 mpData->mpFirstGroup = pGroup->mpNext;
731 delete pGroup;
733 // Rewrite config data
734 if ( !mnLockCount && mbPersistence )
735 ImplWriteConfig( mpData );
736 else
738 mpData->mbModified = true;
741 mnDataUpdateId = mpData->mnDataUpdateId;
742 mpData->mnDataUpdateId++;
746 OString Config::GetGroupName(sal_uInt16 nGroup) const
748 // Update config data if necessary
749 if ( !mnLockCount )
750 ImplUpdateConfig();
752 ImplGroupData* pGroup = mpData->mpFirstGroup;
753 sal_uInt16 nGroupCount = 0;
754 OString aGroupName;
755 while ( pGroup )
757 if ( nGroup == nGroupCount )
759 aGroupName = pGroup->maGroupName;
760 break;
763 nGroupCount++;
764 pGroup = pGroup->mpNext;
767 return aGroupName;
770 sal_uInt16 Config::GetGroupCount() const
772 // Update config data if necessary
773 if ( !mnLockCount )
774 ImplUpdateConfig();
776 ImplGroupData* pGroup = mpData->mpFirstGroup;
777 sal_uInt16 nGroupCount = 0;
778 while ( pGroup )
780 nGroupCount++;
781 pGroup = pGroup->mpNext;
784 return nGroupCount;
787 bool Config::HasGroup(const OString& rGroup) const
789 // Update config data if necessary
790 if ( !mnLockCount )
791 ImplUpdateConfig();
793 ImplGroupData* pGroup = mpData->mpFirstGroup;
794 bool bRet = false;
796 while( pGroup )
798 if( pGroup->maGroupName.equalsIgnoreAsciiCase(rGroup) )
800 bRet = true;
801 break;
804 pGroup = pGroup->mpNext;
807 return bRet;
810 OString Config::ReadKey(const OString& rKey) const
812 return ReadKey(rKey, OString());
815 OString Config::ReadKey(const OString& rKey, const OString& rDefault) const
817 #ifdef DBG_UTIL
818 OStringBuffer aTraceStr("Config::ReadKey( ");
819 aTraceStr.append(rKey);
820 aTraceStr.append(" ) from ");
821 aTraceStr.append(GetGroup());
822 aTraceStr.append(" in ");
823 aTraceStr.append(OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
824 OSL_TRACE("%s", aTraceStr.getStr());
825 #endif
827 // Update config data if necessary
828 if ( !mnLockCount )
829 ImplUpdateConfig();
831 // Search key, return value if found
832 ImplGroupData* pGroup = ImplGetGroup();
833 if ( pGroup )
835 ImplKeyData* pKey = pGroup->mpFirstKey;
836 while ( pKey )
838 if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
839 return pKey->maValue;
841 pKey = pKey->mpNext;
845 return rDefault;
848 void Config::WriteKey(const OString& rKey, const OString& rStr)
850 #ifdef DBG_UTIL
851 OStringBuffer aTraceStr("Config::WriteKey( ");
852 aTraceStr.append(rKey);
853 aTraceStr.append(", ");
854 aTraceStr.append(rStr);
855 aTraceStr.append(" ) to ");
856 aTraceStr.append(GetGroup());
857 aTraceStr.append(" in ");
858 aTraceStr.append(OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
859 OSL_TRACE("%s", aTraceStr.getStr());
860 #endif
862 // Update config data if necessary
863 if ( !mnLockCount || !mpData->mbRead )
865 ImplUpdateConfig();
866 mpData->mbRead = true;
869 // Search key and update value if found
870 ImplGroupData* pGroup = ImplGetGroup();
871 if ( pGroup )
873 ImplKeyData* pPrevKey = NULL;
874 ImplKeyData* pKey = pGroup->mpFirstKey;
875 while ( pKey )
877 if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
878 break;
880 pPrevKey = pKey;
881 pKey = pKey->mpNext;
884 bool bNewValue;
885 if ( !pKey )
887 pKey = new ImplKeyData;
888 pKey->mpNext = NULL;
889 pKey->maKey = rKey;
890 pKey->mbIsComment = false;
891 if ( pPrevKey )
892 pPrevKey->mpNext = pKey;
893 else
894 pGroup->mpFirstKey = pKey;
895 bNewValue = true;
897 else
898 bNewValue = pKey->maValue != rStr;
900 if ( bNewValue )
902 pKey->maValue = rStr;
904 if ( !mnLockCount && mbPersistence )
905 ImplWriteConfig( mpData );
906 else
908 mpData->mbModified = true;
914 void Config::DeleteKey(const OString& rKey)
916 // Update config data if necessary
917 if ( !mnLockCount || !mpData->mbRead )
919 ImplUpdateConfig();
920 mpData->mbRead = true;
923 // Search key and update value
924 ImplGroupData* pGroup = ImplGetGroup();
925 if ( pGroup )
927 ImplKeyData* pPrevKey = NULL;
928 ImplKeyData* pKey = pGroup->mpFirstKey;
929 while ( pKey )
931 if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
932 break;
934 pPrevKey = pKey;
935 pKey = pKey->mpNext;
938 if ( pKey )
940 // Rewire group pointers and delete
941 if ( pPrevKey )
942 pPrevKey->mpNext = pKey->mpNext;
943 else
944 pGroup->mpFirstKey = pKey->mpNext;
945 delete pKey;
947 // Rewrite config file
948 if ( !mnLockCount && mbPersistence )
949 ImplWriteConfig( mpData );
950 else
952 mpData->mbModified = true;
958 sal_uInt16 Config::GetKeyCount() const
960 #ifdef DBG_UTIL
961 OStringBuffer aTraceStr("Config::GetKeyCount()");
962 aTraceStr.append(" from ");
963 aTraceStr.append(GetGroup());
964 aTraceStr.append(" in ");
965 aTraceStr.append(OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
966 OSL_TRACE("%s", aTraceStr.getStr());
967 #endif
969 // Update config data if necessary
970 if ( !mnLockCount )
971 ImplUpdateConfig();
973 // Search key and update value
974 sal_uInt16 nCount = 0;
975 ImplGroupData* pGroup = ImplGetGroup();
976 if ( pGroup )
978 ImplKeyData* pKey = pGroup->mpFirstKey;
979 while ( pKey )
981 if ( !pKey->mbIsComment )
982 nCount++;
984 pKey = pKey->mpNext;
988 return nCount;
991 OString Config::GetKeyName(sal_uInt16 nKey) const
993 #ifdef DBG_UTIL
994 OStringBuffer aTraceStr("Config::GetKeyName( ");
995 aTraceStr.append(static_cast<sal_Int32>(nKey));
996 aTraceStr.append(" ) from ");
997 aTraceStr.append(GetGroup());
998 aTraceStr.append(" in ");
999 aTraceStr.append(OUStringToOString(
1000 maFileName, RTL_TEXTENCODING_UTF8));
1001 OSL_TRACE("%s", aTraceStr.getStr());
1002 #endif
1004 // search key and return name if found
1005 ImplGroupData* pGroup = ImplGetGroup();
1006 if ( pGroup )
1008 ImplKeyData* pKey = pGroup->mpFirstKey;
1009 while ( pKey )
1011 if ( !pKey->mbIsComment )
1013 if ( !nKey )
1014 return pKey->maKey;
1015 nKey--;
1018 pKey = pKey->mpNext;
1022 return OString();
1025 OString Config::ReadKey(sal_uInt16 nKey) const
1027 #ifdef DBG_UTIL
1028 OStringBuffer aTraceStr("Config::ReadKey( ");
1029 aTraceStr.append(static_cast<sal_Int32>(nKey));
1030 aTraceStr.append(" ) from ");
1031 aTraceStr.append(GetGroup());
1032 aTraceStr.append(" in ");
1033 aTraceStr.append(OUStringToOString(maFileName,
1034 RTL_TEXTENCODING_UTF8));
1035 OSL_TRACE("%s", aTraceStr.getStr());
1036 #endif
1038 // Search key and return value if found
1039 ImplGroupData* pGroup = ImplGetGroup();
1040 if ( pGroup )
1042 ImplKeyData* pKey = pGroup->mpFirstKey;
1043 while ( pKey )
1045 if ( !pKey->mbIsComment )
1047 if ( !nKey )
1048 return pKey->maValue;
1049 nKey--;
1052 pKey = pKey->mpNext;
1056 return OString();
1059 void Config::Flush()
1061 if ( mpData->mbModified && mbPersistence )
1062 ImplWriteConfig( mpData );
1065 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */