1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: config.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
45 #include <osl/file.hxx>
46 #include <tools/stream.hxx>
47 #include <tools/debug.hxx>
48 #include <tools/config.hxx>
49 #include <osl/security.h>
51 #define MAXBUFLEN 1024 // Fuer Buffer bei VOS-Funktionen
67 ImplGroupData
* mpNext
;
68 ImplKeyData
* mpFirstKey
;
69 ByteString maGroupName
;
75 ImplGroupData
* mpFirstGroup
;
86 // =======================================================================
88 static ByteString
& getEmptyByteString()
90 static ByteString aEmpty
;
94 // =======================================================================
96 static String
toUncPath( const String
& rPath
)
98 ::rtl::OUString aFileURL
;
100 // check if rFileName is already a URL; if not make it so
101 if( rPath
.CompareToAscii( "file://", 7 ) == COMPARE_EQUAL
)
103 else if( ::osl::FileBase::getFileURLFromSystemPath( rPath
, aFileURL
) != ::osl::FileBase::E_None
)
109 static ULONG
ImplSysGetConfigTimeStamp( const XubString
& rFileName
)
111 ULONG nTimeStamp
= 0;
112 ::osl::DirectoryItem aItem
;
113 ::osl::FileStatus
aStatus( osl_FileStatus_Mask_ModifyTime
);
116 if( ( nError
= ::osl::DirectoryItem::get( rFileName
, aItem
) ) == ::osl::FileBase::E_None
&&
117 aItem
.getFileStatus( aStatus
) == ::osl::FileBase::E_None
)
119 nTimeStamp
= aStatus
.getModifyTime().Seconds
;
125 // -----------------------------------------------------------------------
127 static BYTE
* ImplSysReadConfig( const XubString
& rFileName
,
128 sal_uInt64
& rRead
, BOOL
& rbRead
, BOOL
& rbIsUTF8BOM
, ULONG
& rTimeStamp
)
131 ::osl::File
aFile( rFileName
);
133 if( aFile
.open( osl_File_OpenFlag_Read
) == ::osl::FileBase::E_None
)
135 sal_uInt64 nPos
= 0, nRead
= 0;
136 if( aFile
.getSize( nPos
) == ::osl::FileBase::E_None
)
138 if (nPos
> std::numeric_limits
< std::size_t >::max()) {
142 pBuf
= new BYTE
[static_cast< std::size_t >(nPos
)];
143 if( aFile
.read( pBuf
, nPos
, nRead
) == ::osl::FileBase::E_None
&& nRead
== nPos
)
145 //skip the byte-order-mark 0xEF 0xBB 0xBF, if it was UTF8 files
146 unsigned char BOM
[3] = {0xEF, 0xBB, 0xBF};
147 if (nRead
> 2 && memcmp(pBuf
, BOM
, 3) == 0)
150 rtl_moveMemory(pBuf
, pBuf
+ 3, sal::static_int_cast
<sal_Size
>(nRead
* sizeof(BYTE
)) );
154 rTimeStamp
= ImplSysGetConfigTimeStamp( rFileName
);
170 // -----------------------------------------------------------------------
172 static BOOL
ImplSysWriteConfig( const XubString
& rFileName
,
173 const BYTE
* pBuf
, ULONG nBufLen
, BOOL rbIsUTF8BOM
, ULONG
& rTimeStamp
)
175 BOOL bSuccess
= FALSE
;
176 BOOL bUTF8BOMSuccess
= FALSE
;
178 ::osl::File
aFile( rFileName
);
179 ::osl::FileBase::RC eError
= aFile
.open( osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
180 if( eError
!= ::osl::FileBase::E_None
)
181 eError
= aFile
.open( osl_File_OpenFlag_Write
);
182 if( eError
== ::osl::FileBase::E_None
)
188 //write the the byte-order-mark 0xEF 0xBB 0xBF first , if it was UTF8 files
191 unsigned char BOM
[3] = {0xEF, 0xBB, 0xBF};
192 sal_uInt64 nUTF8BOMWritten
;
193 if( aFile
.write( BOM
, 3, nUTF8BOMWritten
) == ::osl::FileBase::E_None
&& 3 == nUTF8BOMWritten
)
195 bUTF8BOMSuccess
= TRUE
;
199 if( aFile
.write( pBuf
, nBufLen
, nWritten
) == ::osl::FileBase::E_None
&& nWritten
== nBufLen
)
203 if ( rbIsUTF8BOM
? bSuccess
&& bUTF8BOMSuccess
: bSuccess
)
205 rTimeStamp
= ImplSysGetConfigTimeStamp( rFileName
);
209 return rbIsUTF8BOM
? bSuccess
&& bUTF8BOMSuccess
: bSuccess
;
212 // -----------------------------------------------------------------------
214 static String
ImplMakeConfigName( const XubString
* pFileName
,
215 const XubString
* pPathName
)
217 ::rtl::OUString aFileName
;
218 ::rtl::OUString aPathName
;
222 aFileName
= ::rtl::OUString::createFromAscii( "." );
223 aFileName
+= *pFileName
;
224 aFileName
+= ::rtl::OUString::createFromAscii( "rc" );
226 aFileName
= *pFileName
;
227 aFileName
+= ::rtl::OUString::createFromAscii( ".ini" );
233 aFileName
= ::rtl::OUString::createFromAscii( ".sversionrc" );
235 aFileName
= ::rtl::OUString::createFromAscii( "sversion.ini" );
239 // #88208# in case pPathName is set but empty and pFileName is set
240 // and not empty just return the filename; on the default case
241 // prepend default path as usual
242 if ( pPathName
&& pPathName
->Len() )
243 aPathName
= toUncPath( *pPathName
);
244 else if( pPathName
&& pFileName
&& pFileName
->Len() )
248 oslSecurity aSec
= osl_getCurrentSecurity();
249 osl_getConfigDir( aSec
, &aPathName
.pData
);
250 osl_freeSecurityHandle( aSec
);
253 ::rtl::OUString
aName( aPathName
);
254 aName
+= ::rtl::OUString::createFromAscii( "/" );
260 // -----------------------------------------------------------------------
264 ByteString
makeByteString(BYTE
const * p
, sal_uInt64 n
) {
265 if (n
> STRING_MAXLEN
) {
269 ::std::abort(); //TODO: handle this gracefully
273 reinterpret_cast< char const * >(p
),
274 sal::static_int_cast
< xub_StrLen
>(n
));
279 static void ImplMakeConfigList( ImplConfigData
* pData
,
280 const BYTE
* pBuf
, sal_uInt64 nLen
)
282 // kein Buffer, keine Daten
286 // Buffer parsen und Liste zusammenbauen
293 ImplKeyData
* pPrevKey
= NULL
;
295 ImplGroupData
* pPrevGroup
= NULL
;
296 ImplGroupData
* pGroup
= NULL
;
301 if ( pBuf
[i
] == 0x1A )
304 // Spaces und Tabs entfernen
305 while ( (pBuf
[i
] == ' ') || (pBuf
[i
] == '\t') )
308 // Zeilenanfang merken
313 while ( (i
< nLen
) && pBuf
[i
] && (pBuf
[i
] != '\r') && (pBuf
[i
] != '\n') &&
319 // Wenn Zeilenende (CR/LF), dann noch einen weiterschalten
321 (pBuf
[i
] != pBuf
[i
+1]) &&
322 ((pBuf
[i
+1] == '\r') || (pBuf
[i
+1] == '\n')) )
329 pGroup
= new ImplGroupData
;
330 pGroup
->mpNext
= NULL
;
331 pGroup
->mpFirstKey
= NULL
;
332 pGroup
->mnEmptyLines
= 0;
334 pPrevGroup
->mpNext
= pGroup
;
336 pData
->mpFirstGroup
= pGroup
;
341 // Gruppennamen rausfiltern
344 // Spaces und Tabs entfernen
345 while ( (*pLine
== ' ') || (*pLine
== '\t') )
351 while ( (nNameLen
< nLineLen
) && (pLine
[nNameLen
] != ']') )
355 while ( (pLine
[nNameLen
-1] == ' ') || (pLine
[nNameLen
-1] == '\t') )
358 pGroup
->maGroupName
= ByteString( (const sal_Char
*)pLine
, nNameLen
);
364 // Wenn noch keine Gruppe existiert, dann alle Keys in die
368 pGroup
= new ImplGroupData
;
369 pGroup
->mpNext
= NULL
;
370 pGroup
->mpFirstKey
= NULL
;
371 pGroup
->mnEmptyLines
= 0;
373 pPrevGroup
->mpNext
= pGroup
;
375 pData
->mpFirstGroup
= pGroup
;
380 // Falls Leerzeile vorhanden, dann anhaengen
383 while ( pGroup
->mnEmptyLines
)
385 pKey
= new ImplKeyData
;
386 pKey
->mbIsComment
= TRUE
;
387 pPrevKey
->mpNext
= pKey
;
389 pGroup
->mnEmptyLines
--;
393 // Neuen Key erzeugen
394 pKey
= new ImplKeyData
;
397 pPrevKey
->mpNext
= pKey
;
399 pGroup
->mpFirstKey
= pKey
;
401 if ( pLine
[0] == ';' )
403 pKey
->maValue
= makeByteString(pLine
, nLineLen
);
404 pKey
->mbIsComment
= TRUE
;
408 pKey
->mbIsComment
= FALSE
;
410 while ( (nNameLen
< nLineLen
) && (pLine
[nNameLen
] != '=') )
413 // Spaces und Tabs entfernen
416 while ( (pLine
[nNameLen
-1] == ' ') || (pLine
[nNameLen
-1] == '\t') )
419 pKey
->maKey
= ByteString( (const sal_Char
*)pLine
, nNameLen
);
421 if ( nKeyLen
< nLineLen
)
425 // Spaces und Tabs entfernen
426 while ( (*pLine
== ' ') || (*pLine
== '\t') )
433 while ( (pLine
[nLineLen
-1] == ' ') || (pLine
[nLineLen
-1] == '\t') )
435 pKey
->maValue
= makeByteString(pLine
, nLineLen
);
442 // Leerzeilen werden nur gezaehlt und beim Erzeugen des
443 // naechsten Keys angehaengt, da wir Leerzeilen am Ende
444 // einer Gruppe auch nach hinzufuegen von neuen Keys nur
445 // am Ende der Gruppe wieder speichern wollen
447 pGroup
->mnEmptyLines
++;
453 // -----------------------------------------------------------------------
455 static BYTE
* ImplGetConfigBuffer( const ImplConfigData
* pData
, ULONG
& rLen
)
459 BYTE aLineEndBuf
[2] = {0, 0};
461 ImplGroupData
* pGroup
;
462 unsigned int nBufLen
;
467 if ( pData
->meLineEnd
== LINEEND_CR
)
469 aLineEndBuf
[0] = _CR
;
472 else if ( pData
->meLineEnd
== LINEEND_LF
)
474 aLineEndBuf
[0] = _LF
;
479 aLineEndBuf
[0] = _CR
;
480 aLineEndBuf
[1] = _LF
;
484 // Buffergroesse ermitteln
486 pGroup
= pData
->mpFirstGroup
;
489 // Leere Gruppen werden nicht geschrieben
490 if ( pGroup
->mpFirstKey
)
492 nBufLen
+= pGroup
->maGroupName
.Len() + nLineEndLen
+ 2;
493 pKey
= pGroup
->mpFirstKey
;
496 nValueLen
= pKey
->maValue
.Len();
497 if ( pKey
->mbIsComment
)
498 nBufLen
+= nValueLen
+ nLineEndLen
;
500 nBufLen
+= pKey
->maKey
.Len() + nValueLen
+ nLineEndLen
+ 1;
505 // Leerzeile nach jeder Gruppe auch wieder speichern
506 if ( !pGroup
->mnEmptyLines
)
507 pGroup
->mnEmptyLines
= 1;
508 nBufLen
+= nLineEndLen
* pGroup
->mnEmptyLines
;
511 pGroup
= pGroup
->mpNext
;
514 // Laenge dem Aufrufer mitteilen
518 pWriteBuf
= new BYTE
[nLineEndLen
];
521 pWriteBuf
[0] = aLineEndBuf
[0];
522 if ( nLineEndLen
== 2 )
523 pWriteBuf
[1] = aLineEndBuf
[1];
530 // Schreibbuffer anlegen (wird vom Aufrufer zerstoert)
531 pWriteBuf
= new BYTE
[nBufLen
];
537 pGroup
= pData
->mpFirstGroup
;
540 // Leere Gruppen werden nicht geschrieben
541 if ( pGroup
->mpFirstKey
)
544 memcpy( pBuf
, pGroup
->maGroupName
.GetBuffer(), pGroup
->maGroupName
.Len() );
545 pBuf
+= pGroup
->maGroupName
.Len();
547 *pBuf
= aLineEndBuf
[0]; pBuf
++;
548 if ( nLineEndLen
== 2 )
550 *pBuf
= aLineEndBuf
[1]; pBuf
++;
552 pKey
= pGroup
->mpFirstKey
;
555 nValueLen
= pKey
->maValue
.Len();
556 if ( pKey
->mbIsComment
)
560 memcpy( pBuf
, pKey
->maValue
.GetBuffer(), nValueLen
);
563 *pBuf
= aLineEndBuf
[0]; pBuf
++;
564 if ( nLineEndLen
== 2 )
566 *pBuf
= aLineEndBuf
[1]; pBuf
++;
571 nKeyLen
= pKey
->maKey
.Len();
572 memcpy( pBuf
, pKey
->maKey
.GetBuffer(), nKeyLen
);
575 memcpy( pBuf
, pKey
->maValue
.GetBuffer(), nValueLen
);
577 *pBuf
= aLineEndBuf
[0]; pBuf
++;
578 if ( nLineEndLen
== 2 )
580 *pBuf
= aLineEndBuf
[1]; pBuf
++;
587 // Leerzeile nach jeder Gruppe auch wieder speichern
588 USHORT nEmptyLines
= pGroup
->mnEmptyLines
;
589 while ( nEmptyLines
)
591 *pBuf
= aLineEndBuf
[0]; pBuf
++;
592 if ( nLineEndLen
== 2 )
594 *pBuf
= aLineEndBuf
[1]; pBuf
++;
600 pGroup
= pGroup
->mpNext
;
606 // -----------------------------------------------------------------------
608 static void ImplReadConfig( ImplConfigData
* pData
)
610 ULONG nTimeStamp
= 0;
611 sal_uInt64 nRead
= 0;
613 BOOL bIsUTF8BOM
=FALSE
;
614 BYTE
* pBuf
= ImplSysReadConfig( pData
->maFileName
, nRead
, bRead
, bIsUTF8BOM
, nTimeStamp
);
616 // Aus dem Buffer die Config-Verwaltungsliste aufbauen
619 ImplMakeConfigList( pData
, pBuf
, nRead
);
622 pData
->mnTimeStamp
= nTimeStamp
;
623 pData
->mbModified
= FALSE
;
625 pData
->mbRead
= TRUE
;
627 pData
->mbIsUTF8BOM
= TRUE
;
630 // -----------------------------------------------------------------------
632 static void ImplWriteConfig( ImplConfigData
* pData
)
637 if ( pData
->mnTimeStamp
!= ImplSysGetConfigTimeStamp( pData
->maFileName
) )
639 DBG_ERROR1( "Config overwrites modified configfile:\n %s", ByteString( pData
->maFileName
, RTL_TEXTENCODING_UTF8
).GetBuffer() );
644 // Aus der Config-Liste einen Buffer zusammenbauen
646 BYTE
* pBuf
= ImplGetConfigBuffer( pData
, nBufLen
);
649 if ( ImplSysWriteConfig( pData
->maFileName
, pBuf
, nBufLen
, pData
->mbIsUTF8BOM
, pData
->mnTimeStamp
) )
650 pData
->mbModified
= FALSE
;
654 pData
->mbModified
= FALSE
;
657 // -----------------------------------------------------------------------
659 static void ImplDeleteConfigData( ImplConfigData
* pData
)
661 ImplKeyData
* pTempKey
;
663 ImplGroupData
* pTempGroup
;
664 ImplGroupData
* pGroup
= pData
->mpFirstGroup
;
667 pTempGroup
= pGroup
->mpNext
;
669 // Alle Keys loeschen
670 pKey
= pGroup
->mpFirstKey
;
673 pTempKey
= pKey
->mpNext
;
678 // Gruppe loeschen und weiterschalten
683 pData
->mpFirstGroup
= NULL
;
686 // =======================================================================
688 static ImplConfigData
* ImplGetConfigData( const XubString
& rFileName
)
690 ImplConfigData
* pData
;
692 pData
= new ImplConfigData
;
693 pData
->maFileName
= rFileName
;
694 pData
->mpFirstGroup
= NULL
;
695 pData
->mnDataUpdateId
= 0;
696 pData
->meLineEnd
= LINEEND_CRLF
;
697 pData
->mnRefCount
= 0;
698 pData
->mbRead
= FALSE
;
699 pData
->mbIsUTF8BOM
= FALSE
;
700 ImplReadConfig( pData
);
705 // -----------------------------------------------------------------------
707 static void ImplFreeConfigData( ImplConfigData
* pDelData
)
709 ImplDeleteConfigData( pDelData
);
713 // =======================================================================
715 BOOL
Config::ImplUpdateConfig() const
717 // Wenn sich TimeStamp unterscheidet, dann Datei neu einlesen
718 if ( mpData
->mnTimeStamp
!= ImplSysGetConfigTimeStamp( maFileName
) )
720 ImplDeleteConfigData( mpData
);
721 ImplReadConfig( mpData
);
722 mpData
->mnDataUpdateId
++;
729 // -----------------------------------------------------------------------
731 ImplGroupData
* Config::ImplGetGroup() const
733 if ( !mpActGroup
|| (mnDataUpdateId
!= mpData
->mnDataUpdateId
) )
735 ImplGroupData
* pPrevGroup
= NULL
;
736 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
739 if ( pGroup
->maGroupName
.EqualsIgnoreCaseAscii( maGroupName
) )
743 pGroup
= pGroup
->mpNext
;
746 // Falls Gruppe noch nicht existiert, dann dazufuegen
749 pGroup
= new ImplGroupData
;
750 pGroup
->mpNext
= NULL
;
751 pGroup
->mpFirstKey
= NULL
;
752 pGroup
->mnEmptyLines
= 1;
754 pPrevGroup
->mpNext
= pGroup
;
756 mpData
->mpFirstGroup
= pGroup
;
759 // Gruppenname immer uebernehmen, da er auch in dieser Form
760 // geschrieben werden soll. Ausserdem die Cache-Members der
761 // Config-Klasse updaten
762 pGroup
->maGroupName
= maGroupName
;
763 ((Config
*)this)->mnDataUpdateId
= mpData
->mnDataUpdateId
;
764 ((Config
*)this)->mpActGroup
= pGroup
;
770 // =======================================================================
774 // Daten initialisieren und einlesen
775 maFileName
= ImplMakeConfigName( NULL
, NULL
);
776 mpData
= ImplGetConfigData( maFileName
);
780 mbPersistence
= TRUE
;
783 DBG_TRACE( "Config::Config()" );
787 // -----------------------------------------------------------------------
789 Config::Config( const XubString
& rFileName
)
791 // Daten initialisieren und einlesen
792 maFileName
= toUncPath( rFileName
);
793 mpData
= ImplGetConfigData( maFileName
);
797 mbPersistence
= TRUE
;
800 ByteString
aTraceStr( "Config::Config( " );
801 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
803 DBG_TRACE( aTraceStr
.GetBuffer() );
807 // -----------------------------------------------------------------------
812 DBG_TRACE( "Config::~Config()" );
816 ImplFreeConfigData( mpData
);
819 // -----------------------------------------------------------------------
821 String
Config::GetDefDirectory()
823 ::rtl::OUString aDefConfig
;
824 oslSecurity aSec
= osl_getCurrentSecurity();
825 osl_getConfigDir( aSec
, &aDefConfig
.pData
);
826 osl_freeSecurityHandle( aSec
);
831 // -----------------------------------------------------------------------
833 XubString
Config::GetConfigName( const XubString
& rPath
,
834 const XubString
& rBaseName
)
836 return ImplMakeConfigName( &rBaseName
, &rPath
);
839 // -----------------------------------------------------------------------
841 void Config::SetGroup( const ByteString
& rGroup
)
843 // Wenn neue Gruppe gesetzt wird, muss beim naechsten mal die
844 // Gruppe neu ermittelt werden
845 if ( maGroupName
!= rGroup
)
847 maGroupName
= rGroup
;
848 mnDataUpdateId
= mpData
->mnDataUpdateId
-1;
852 // -----------------------------------------------------------------------
854 void Config::DeleteGroup( const ByteString
& rGroup
)
856 // Config-Daten evt. updaten
857 if ( !mnLockCount
|| !mpData
->mbRead
)
860 mpData
->mbRead
= TRUE
;
863 ImplGroupData
* pPrevGroup
= NULL
;
864 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
867 if ( pGroup
->maGroupName
.EqualsIgnoreCaseAscii( rGroup
) )
871 pGroup
= pGroup
->mpNext
;
876 // Alle Keys loeschen
877 ImplKeyData
* pTempKey
;
878 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
881 pTempKey
= pKey
->mpNext
;
886 // Gruppe weiterschalten und loeschen
888 pPrevGroup
->mpNext
= pGroup
->mpNext
;
890 mpData
->mpFirstGroup
= pGroup
->mpNext
;
893 // Config-Datei neu schreiben
894 if ( !mnLockCount
&& mbPersistence
)
895 ImplWriteConfig( mpData
);
898 mpData
->mbModified
= TRUE
;
901 // Gruppen auf ungluetig setzen
902 mnDataUpdateId
= mpData
->mnDataUpdateId
;
903 mpData
->mnDataUpdateId
++;
907 // -----------------------------------------------------------------------
909 ByteString
Config::GetGroupName( USHORT nGroup
) const
911 // Config-Daten evt. updaten
915 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
916 USHORT nGroupCount
= 0;
917 ByteString aGroupName
;
920 if ( nGroup
== nGroupCount
)
922 aGroupName
= pGroup
->maGroupName
;
927 pGroup
= pGroup
->mpNext
;
933 // -----------------------------------------------------------------------
935 USHORT
Config::GetGroupCount() const
937 // Config-Daten evt. updaten
941 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
942 USHORT nGroupCount
= 0;
946 pGroup
= pGroup
->mpNext
;
952 // -----------------------------------------------------------------------
954 BOOL
Config::HasGroup( const ByteString
& rGroup
) const
956 // Config-Daten evt. updaten
960 ImplGroupData
* pGroup
= mpData
->mpFirstGroup
;
965 if( pGroup
->maGroupName
.EqualsIgnoreCaseAscii( rGroup
) )
971 pGroup
= pGroup
->mpNext
;
977 // -----------------------------------------------------------------------
979 ByteString
Config::ReadKey( const ByteString
& rKey
) const
981 return ReadKey( rKey
, getEmptyByteString() );
984 // -----------------------------------------------------------------------
986 UniString
Config::ReadKey( const ByteString
& rKey
, rtl_TextEncoding eEncoding
) const
988 if ( mpData
->mbIsUTF8BOM
)
989 eEncoding
= RTL_TEXTENCODING_UTF8
;
990 return UniString( ReadKey( rKey
), eEncoding
);
993 // -----------------------------------------------------------------------
995 ByteString
Config::ReadKey( const ByteString
& rKey
, const ByteString
& rDefault
) const
998 ByteString
aTraceStr( "Config::ReadKey( " );
1000 aTraceStr
+= " ) from ";
1001 aTraceStr
+= GetGroup();
1002 aTraceStr
+= " in ";
1003 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
1004 DBG_TRACE( aTraceStr
.GetBuffer() );
1007 // Config-Daten evt. updaten
1011 // Key suchen und Value zurueckgeben
1012 ImplGroupData
* pGroup
= ImplGetGroup();
1015 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1018 if ( !pKey
->mbIsComment
&& pKey
->maKey
.EqualsIgnoreCaseAscii( rKey
) )
1019 return pKey
->maValue
;
1021 pKey
= pKey
->mpNext
;
1028 // -----------------------------------------------------------------------
1030 void Config::WriteKey( const ByteString
& rKey
, const ByteString
& rStr
)
1033 ByteString
aTraceStr( "Config::WriteKey( " );
1037 aTraceStr
+= " ) to ";
1038 aTraceStr
+= GetGroup();
1039 aTraceStr
+= " in ";
1040 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
1041 DBG_TRACE( aTraceStr
.GetBuffer() );
1042 DBG_ASSERTWARNING( rStr
!= ReadKey( rKey
), "Config::WriteKey() with the same Value" );
1045 // Config-Daten evt. updaten
1046 if ( !mnLockCount
|| !mpData
->mbRead
)
1049 mpData
->mbRead
= TRUE
;
1052 // Key suchen und Value setzen
1053 ImplGroupData
* pGroup
= ImplGetGroup();
1056 ImplKeyData
* pPrevKey
= NULL
;
1057 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1060 if ( !pKey
->mbIsComment
&& pKey
->maKey
.EqualsIgnoreCaseAscii( rKey
) )
1064 pKey
= pKey
->mpNext
;
1070 pKey
= new ImplKeyData
;
1071 pKey
->mpNext
= NULL
;
1073 pKey
->mbIsComment
= FALSE
;
1075 pPrevKey
->mpNext
= pKey
;
1077 pGroup
->mpFirstKey
= pKey
;
1081 bNewValue
= pKey
->maValue
!= rStr
;
1085 pKey
->maValue
= rStr
;
1087 if ( !mnLockCount
&& mbPersistence
)
1088 ImplWriteConfig( mpData
);
1091 mpData
->mbModified
= TRUE
;
1097 // -----------------------------------------------------------------------
1099 void Config::WriteKey( const ByteString
& rKey
, const UniString
& rValue
, rtl_TextEncoding eEncoding
)
1101 if ( mpData
->mbIsUTF8BOM
)
1102 eEncoding
= RTL_TEXTENCODING_UTF8
;
1103 WriteKey( rKey
, ByteString( rValue
, eEncoding
) );
1106 // -----------------------------------------------------------------------
1108 void Config::DeleteKey( const ByteString
& rKey
)
1110 // Config-Daten evt. updaten
1111 if ( !mnLockCount
|| !mpData
->mbRead
)
1114 mpData
->mbRead
= TRUE
;
1117 // Key suchen und Value setzen
1118 ImplGroupData
* pGroup
= ImplGetGroup();
1121 ImplKeyData
* pPrevKey
= NULL
;
1122 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1125 if ( !pKey
->mbIsComment
&& pKey
->maKey
.EqualsIgnoreCaseAscii( rKey
) )
1129 pKey
= pKey
->mpNext
;
1134 // Gruppe weiterschalten und loeschen
1136 pPrevKey
->mpNext
= pKey
->mpNext
;
1138 pGroup
->mpFirstKey
= pKey
->mpNext
;
1141 // Config-Datei neu schreiben
1142 if ( !mnLockCount
&& mbPersistence
)
1143 ImplWriteConfig( mpData
);
1146 mpData
->mbModified
= TRUE
;
1152 // -----------------------------------------------------------------------
1154 USHORT
Config::GetKeyCount() const
1157 ByteString
aTraceStr( "Config::GetKeyCount()" );
1158 aTraceStr
+= " from ";
1159 aTraceStr
+= GetGroup();
1160 aTraceStr
+= " in ";
1161 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
1162 DBG_TRACE( aTraceStr
.GetBuffer() );
1165 // Config-Daten evt. updaten
1169 // Key suchen und Value zurueckgeben
1171 ImplGroupData
* pGroup
= ImplGetGroup();
1174 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1177 if ( !pKey
->mbIsComment
)
1180 pKey
= pKey
->mpNext
;
1187 // -----------------------------------------------------------------------
1189 ByteString
Config::GetKeyName( USHORT nKey
) const
1192 ByteString
aTraceStr( "Config::GetKeyName( " );
1193 aTraceStr
+= ByteString::CreateFromInt32(nKey
);
1194 aTraceStr
+= " ) from ";
1195 aTraceStr
+= GetGroup();
1196 aTraceStr
+= " in ";
1197 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
1198 DBG_TRACE( aTraceStr
.GetBuffer() );
1201 // Key suchen und Name zurueckgeben
1202 ImplGroupData
* pGroup
= ImplGetGroup();
1205 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1208 if ( !pKey
->mbIsComment
)
1215 pKey
= pKey
->mpNext
;
1219 return getEmptyByteString();
1222 // -----------------------------------------------------------------------
1224 ByteString
Config::ReadKey( USHORT nKey
) const
1227 ByteString
aTraceStr( "Config::ReadKey( " );
1228 aTraceStr
+= ByteString::CreateFromInt32( nKey
);
1229 aTraceStr
+= " ) from ";
1230 aTraceStr
+= GetGroup();
1231 aTraceStr
+= " in ";
1232 aTraceStr
+= ByteString( maFileName
, RTL_TEXTENCODING_UTF8
);
1233 DBG_TRACE( aTraceStr
.GetBuffer() );
1236 // Key suchen und Value zurueckgeben
1237 ImplGroupData
* pGroup
= ImplGetGroup();
1240 ImplKeyData
* pKey
= pGroup
->mpFirstKey
;
1243 if ( !pKey
->mbIsComment
)
1246 return pKey
->maValue
;
1250 pKey
= pKey
->mpNext
;
1254 return getEmptyByteString();
1257 // -----------------------------------------------------------------------
1259 void Config::EnterLock()
1261 // Config-Daten evt. updaten
1268 // -----------------------------------------------------------------------
1270 void Config::LeaveLock()
1272 DBG_ASSERT( mnLockCount
, "Config::LeaveLook() without Config::EnterLook()" );
1275 if ( (mnLockCount
== 0) && mpData
->mbModified
&& mbPersistence
)
1276 ImplWriteConfig( mpData
);
1279 // -----------------------------------------------------------------------
1281 BOOL
Config::Update()
1283 return ImplUpdateConfig();
1286 // -----------------------------------------------------------------------
1288 void Config::Flush()
1290 if ( mpData
->mbModified
&& mbPersistence
)
1291 ImplWriteConfig( mpData
);
1294 // -----------------------------------------------------------------------
1296 void Config::SetLineEnd( LineEnd eLineEnd
)
1298 mpData
->meLineEnd
= eLineEnd
;
1301 // -----------------------------------------------------------------------
1303 LineEnd
Config::GetLineEnd() const
1305 return mpData
->meLineEnd
;