1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
47 ImplGroupData
* mpNext
;
48 ImplKeyData
* mpFirstKey
;
50 sal_uInt16 mnEmptyLines
;
55 ImplGroupData
* mpFirstGroup
;
57 sal_uIntPtr mnDataUpdateId
;
58 sal_uIntPtr mnTimeStamp
;
60 sal_uInt16 mnRefCount
;
66 static OUString
toUncPath( const OUString
& rPath
)
70 // check if rFileName is already a URL; if not make it so
71 if( rPath
.startsWith( "file://"))
75 else if( ::osl::FileBase::getFileURLFromSystemPath( rPath
, aFileURL
) != ::osl::FileBase::E_None
)
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
;
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
)
106 if( aFile
.getSize( nPos
) == ::osl::FileBase::E_None
)
108 if (nPos
> SAL_MAX_SIZE
) {
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)
121 memmove(pBuf
, pBuf
+ 3, sal::static_int_cast
<sal_Size
>(nRead
* sizeof(sal_uInt8
)) );
125 rTimeStamp
= ImplSysGetConfigTimeStamp( rFileName
);
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
)
157 //write the byte-order-mark 0xEF 0xBB 0xBF first , if it was UTF8 files
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
)
172 if ( rbIsUTF8BOM
? bSuccess
&& bUTF8BOMSuccess
: bSuccess
)
174 rTimeStamp
= ImplSysGetConfigTimeStamp( rFileName
);
178 return rbIsUTF8BOM
? bSuccess
&& bUTF8BOMSuccess
: bSuccess
;
182 OString
makeOString(const sal_uInt8
* p
, sal_uInt64 n
)
184 if (n
> SAL_MAX_INT32
)
189 ::std::abort(); //TODO: handle this gracefully
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
)
204 // Parse buffer and build config list
210 const sal_uInt8
* pLine
;
211 ImplKeyData
* pPrevKey
= NULL
;
213 ImplGroupData
* pPrevGroup
= NULL
;
214 ImplGroupData
* pGroup
= NULL
;
219 if ( pBuf
[i
] == 0x1A )
222 // Remove spaces and tabs
223 while ( (pBuf
[i
] == ' ') || (pBuf
[i
] == '\t') )
226 // remember line-starts
230 // search line-endings
231 while ( (i
< nLen
) && pBuf
[i
] && (pBuf
[i
] != '\r') && (pBuf
[i
] != '\n') &&
237 // if Line-ending is found, continue once
239 (pBuf
[i
] != pBuf
[i
+1]) &&
240 ((pBuf
[i
+1] == '\r') || (pBuf
[i
+1] == '\n')) )
247 pGroup
= new ImplGroupData
;
248 pGroup
->mpNext
= NULL
;
249 pGroup
->mpFirstKey
= NULL
;
250 pGroup
->mnEmptyLines
= 0;
252 pPrevGroup
->mpNext
= pGroup
;
254 pData
->mpFirstGroup
= pGroup
;
259 // filter group names
262 // remove spaces and tabs
263 while ( (*pLine
== ' ') || (*pLine
== '\t') )
269 while ( (nNameLen
< nLineLen
) && (pLine
[nNameLen
] != ']') )
273 while ( (pLine
[nNameLen
-1] == ' ') || (pLine
[nNameLen
-1] == '\t') )
276 pGroup
->maGroupName
= makeOString(pLine
, nNameLen
);
282 // If no group exists yet, add to default
285 pGroup
= new ImplGroupData
;
286 pGroup
->mpNext
= NULL
;
287 pGroup
->mpFirstKey
= NULL
;
288 pGroup
->mnEmptyLines
= 0;
289 pData
->mpFirstGroup
= pGroup
;
294 // if empty line, append it
297 while ( pGroup
->mnEmptyLines
)
299 pKey
= new ImplKeyData
;
300 pKey
->mbIsComment
= true;
301 pPrevKey
->mpNext
= pKey
;
303 pGroup
->mnEmptyLines
--;
308 pKey
= new ImplKeyData
;
311 pPrevKey
->mpNext
= pKey
;
313 pGroup
->mpFirstKey
= pKey
;
315 if ( pLine
[0] == ';' )
317 pKey
->maValue
= makeOString(pLine
, nLineLen
);
318 pKey
->mbIsComment
= true;
322 pKey
->mbIsComment
= false;
324 while ( (nNameLen
< nLineLen
) && (pLine
[nNameLen
] != '=') )
327 // Remove spaces and tabs
330 while ( (pLine
[nNameLen
-1] == ' ') || (pLine
[nNameLen
-1] == '\t') )
333 pKey
->maKey
= makeOString(pLine
, nNameLen
);
335 if ( nKeyLen
< nLineLen
)
339 // Remove spaces and tabs
340 while ( (*pLine
== ' ') || (*pLine
== '\t') )
347 while ( (pLine
[nLineLen
-1] == ' ') || (pLine
[nLineLen
-1] == '\t') )
349 pKey
->maValue
= makeOString(pLine
, nLineLen
);
356 // Spaces are counted and appended only after key generation,
357 // as we want to store spaces even after adding new keys
359 pGroup
->mnEmptyLines
++;
365 static sal_uInt8
* ImplGetConfigBuffer( const ImplConfigData
* pData
, sal_uIntPtr
& rLen
)
367 sal_uInt8
* pWriteBuf
;
369 sal_uInt8 aLineEndBuf
[2] = {0, 0};
371 ImplGroupData
* pGroup
;
372 unsigned int nBufLen
;
373 sal_uInt32 nValueLen
;
375 sal_uInt32 nLineEndLen
;
377 if ( pData
->meLineEnd
== LINEEND_CR
)
379 aLineEndBuf
[0] = '\r';
382 else if ( pData
->meLineEnd
== LINEEND_LF
)
384 aLineEndBuf
[0] = '\n';
389 aLineEndBuf
[0] = '\r';
390 aLineEndBuf
[1] = '\n';
395 pGroup
= pData
->mpFirstGroup
;
398 // Don't write empty groups
399 if ( pGroup
->mpFirstKey
)
401 nBufLen
+= pGroup
->maGroupName
.getLength() + nLineEndLen
+ 2;
402 pKey
= pGroup
->mpFirstKey
;
405 nValueLen
= pKey
->maValue
.getLength();
406 if ( pKey
->mbIsComment
)
407 nBufLen
+= nValueLen
+ nLineEndLen
;
409 nBufLen
+= pKey
->maKey
.getLength() + nValueLen
+ nLineEndLen
+ 1;
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
427 pWriteBuf
= new sal_uInt8
[nLineEndLen
];
430 pWriteBuf
[0] = aLineEndBuf
[0];
431 if ( nLineEndLen
== 2 )
432 pWriteBuf
[1] = aLineEndBuf
[1];
439 // Allocate new write buffer (caller frees it)
440 pWriteBuf
= new sal_uInt8
[nBufLen
];
446 pGroup
= pData
->mpFirstGroup
;
449 // Don't write empty groups
450 if ( pGroup
->mpFirstKey
)
453 memcpy( pBuf
, pGroup
->maGroupName
.getStr(), pGroup
->maGroupName
.getLength() );
454 pBuf
+= pGroup
->maGroupName
.getLength();
456 *pBuf
= aLineEndBuf
[0]; pBuf
++;
457 if ( nLineEndLen
== 2 )
459 *pBuf
= aLineEndBuf
[1]; pBuf
++;
461 pKey
= pGroup
->mpFirstKey
;
464 nValueLen
= pKey
->maValue
.getLength();
465 if ( pKey
->mbIsComment
)
469 memcpy( pBuf
, pKey
->maValue
.getStr(), nValueLen
);
472 *pBuf
= aLineEndBuf
[0]; pBuf
++;
473 if ( nLineEndLen
== 2 )
475 *pBuf
= aLineEndBuf
[1]; pBuf
++;
480 nKeyLen
= pKey
->maKey
.getLength();
481 memcpy( pBuf
, pKey
->maKey
.getStr(), nKeyLen
);
484 memcpy( pBuf
, pKey
->maValue
.getStr(), nValueLen
);
486 *pBuf
= aLineEndBuf
[0]; pBuf
++;
487 if ( nLineEndLen
== 2 )
489 *pBuf
= aLineEndBuf
[1]; pBuf
++;
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
++;
509 pGroup
= pGroup
->mpNext
;
515 static void ImplReadConfig( ImplConfigData
* pData
)
517 sal_uIntPtr nTimeStamp
= 0;
518 sal_uInt64 nRead
= 0;
520 bool bIsUTF8BOM
= false;
521 sal_uInt8
* pBuf
= ImplSysReadConfig( pData
->maFileName
, nRead
, bRead
, bIsUTF8BOM
, nTimeStamp
);
523 // Read config list from buffer
526 ImplMakeConfigList( pData
, pBuf
, nRead
);
529 pData
->mnTimeStamp
= nTimeStamp
;
530 pData
->mbModified
= false;
532 pData
->mbRead
= true;
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
544 sal_uInt8
* pBuf
= ImplGetConfigBuffer( pData
, nBufLen
);
547 if ( ImplSysWriteConfig( pData
->maFileName
, pBuf
, nBufLen
, pData
->mbIsUTF8BOM
, pData
->mnTimeStamp
) )
548 pData
->mbModified
= false;
552 pData
->mbModified
= false;
555 static void ImplDeleteConfigData( ImplConfigData
* pData
)
557 ImplKeyData
* pTempKey
;
559 ImplGroupData
* pTempGroup
;
560 ImplGroupData
* pGroup
= pData
->mpFirstGroup
;
563 pTempGroup
= pGroup
->mpNext
;
566 pKey
= pGroup
->mpFirstKey
;
569 pTempKey
= pKey
->mpNext
;
574 // remove group and continue
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
);
599 static void ImplFreeConfigData( ImplConfigData
* pDelData
)
601 ImplDeleteConfigData( 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
++;
619 ImplGroupData
* Config::ImplGetGroup() const
621 if ( !mpActGroup
|| (mnDataUpdateId
!= mpData
->mnDataUpdateId
) )
623 ImplGroupData
* pPrevGroup
= NULL
;
624 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
627 if ( pGroup
->maGroupName
.equalsIgnoreAsciiCase(maGroupName
) )
631 pGroup
= pGroup
->mpNext
;
634 // Add group if not exists
637 pGroup
= new ImplGroupData
;
638 pGroup
->mpNext
= NULL
;
639 pGroup
->mpFirstKey
= NULL
;
640 pGroup
->mnEmptyLines
= 1;
642 pPrevGroup
->mpNext
= pGroup
;
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
;
656 Config::Config( const OUString
& rFileName
)
658 // Initialize config data
659 maFileName
= toUncPath( rFileName
);
660 mpData
= ImplGetConfigData( maFileName
);
664 mbPersistence
= true;
667 OStringBuffer
aTraceStr("Config::Config( ");
668 aTraceStr
.append(OUStringToOString(maFileName
, RTL_TEXTENCODING_UTF8
));
669 aTraceStr
.append(" )");
670 OSL_TRACE("%s", aTraceStr
.getStr());
677 OSL_TRACE( "Config::~Config()" );
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
)
700 mpData
->mbRead
= true;
703 ImplGroupData
* pPrevGroup
= NULL
;
704 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
707 if ( pGroup
->maGroupName
.equalsIgnoreAsciiCase(rGroup
) )
711 pGroup
= pGroup
->mpNext
;
717 ImplKeyData
* pTempKey
;
718 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
721 pTempKey
= pKey
->mpNext
;
726 // Rewire pointers and remove group
728 pPrevGroup
->mpNext
= pGroup
->mpNext
;
730 mpData
->mpFirstGroup
= pGroup
->mpNext
;
733 // Rewrite config data
734 if ( !mnLockCount
&& mbPersistence
)
735 ImplWriteConfig( mpData
);
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
752 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
753 sal_uInt16 nGroupCount
= 0;
757 if ( nGroup
== nGroupCount
)
759 aGroupName
= pGroup
->maGroupName
;
764 pGroup
= pGroup
->mpNext
;
770 sal_uInt16
Config::GetGroupCount() const
772 // Update config data if necessary
776 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
777 sal_uInt16 nGroupCount
= 0;
781 pGroup
= pGroup
->mpNext
;
787 bool Config::HasGroup(const OString
& rGroup
) const
789 // Update config data if necessary
793 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
798 if( pGroup
->maGroupName
.equalsIgnoreAsciiCase(rGroup
) )
804 pGroup
= pGroup
->mpNext
;
810 OString
Config::ReadKey(const OString
& rKey
) const
812 return ReadKey(rKey
, OString());
815 OString
Config::ReadKey(const OString
& rKey
, const OString
& rDefault
) const
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());
827 // Update config data if necessary
831 // Search key, return value if found
832 ImplGroupData
* pGroup
= ImplGetGroup();
835 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
838 if ( !pKey
->mbIsComment
&& pKey
->maKey
.equalsIgnoreAsciiCase(rKey
) )
839 return pKey
->maValue
;
848 void Config::WriteKey(const OString
& rKey
, const OString
& rStr
)
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());
862 // Update config data if necessary
863 if ( !mnLockCount
|| !mpData
->mbRead
)
866 mpData
->mbRead
= true;
869 // Search key and update value if found
870 ImplGroupData
* pGroup
= ImplGetGroup();
873 ImplKeyData
* pPrevKey
= NULL
;
874 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
877 if ( !pKey
->mbIsComment
&& pKey
->maKey
.equalsIgnoreAsciiCase(rKey
) )
887 pKey
= new ImplKeyData
;
890 pKey
->mbIsComment
= false;
892 pPrevKey
->mpNext
= pKey
;
894 pGroup
->mpFirstKey
= pKey
;
898 bNewValue
= pKey
->maValue
!= rStr
;
902 pKey
->maValue
= rStr
;
904 if ( !mnLockCount
&& mbPersistence
)
905 ImplWriteConfig( mpData
);
908 mpData
->mbModified
= true;
914 void Config::DeleteKey(const OString
& rKey
)
916 // Update config data if necessary
917 if ( !mnLockCount
|| !mpData
->mbRead
)
920 mpData
->mbRead
= true;
923 // Search key and update value
924 ImplGroupData
* pGroup
= ImplGetGroup();
927 ImplKeyData
* pPrevKey
= NULL
;
928 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
931 if ( !pKey
->mbIsComment
&& pKey
->maKey
.equalsIgnoreAsciiCase(rKey
) )
940 // Rewire group pointers and delete
942 pPrevKey
->mpNext
= pKey
->mpNext
;
944 pGroup
->mpFirstKey
= pKey
->mpNext
;
947 // Rewrite config file
948 if ( !mnLockCount
&& mbPersistence
)
949 ImplWriteConfig( mpData
);
952 mpData
->mbModified
= true;
958 sal_uInt16
Config::GetKeyCount() const
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());
969 // Update config data if necessary
973 // Search key and update value
974 sal_uInt16 nCount
= 0;
975 ImplGroupData
* pGroup
= ImplGetGroup();
978 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
981 if ( !pKey
->mbIsComment
)
991 OString
Config::GetKeyName(sal_uInt16 nKey
) const
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());
1004 // search key and return name if found
1005 ImplGroupData
* pGroup
= ImplGetGroup();
1008 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1011 if ( !pKey
->mbIsComment
)
1018 pKey
= pKey
->mpNext
;
1025 OString
Config::ReadKey(sal_uInt16 nKey
) const
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());
1038 // Search key and return value if found
1039 ImplGroupData
* pGroup
= ImplGetGroup();
1042 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1045 if ( !pKey
->mbIsComment
)
1048 return pKey
->maValue
;
1052 pKey
= pKey
->mpNext
;
1059 void Config::Flush()
1061 if ( mpData
->mbModified
&& mbPersistence
)
1062 ImplWriteConfig( mpData
);
1065 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */