LCOV - code coverage report
Current view: top level - tools/source/generic - config.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 374 500 74.8 %
Date: 2012-08-25 Functions: 31 36 86.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 232 456 50.9 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       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/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      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 .
      18                 :            :  */
      19                 :            : #define _CONFIG_CXX
      20                 :            : 
      21                 :            : #include <cstddef>
      22                 :            : #include <cstdlib>
      23                 :            : #include <limits>
      24                 :            : #include <new>
      25                 :            : #include <string.h>
      26                 :            : 
      27                 :            : #ifdef WNT
      28                 :            : #include "stdlib.h"
      29                 :            : #endif
      30                 :            : 
      31                 :            : #include <osl/file.hxx>
      32                 :            : #include <tools/stream.hxx>
      33                 :            : #include <tools/debug.hxx>
      34                 :            : #include <tools/config.hxx>
      35                 :            : #include <osl/security.h>
      36                 :            : #include <rtl/strbuf.hxx>
      37                 :            : 
      38                 :      40684 : struct ImplKeyData
      39                 :            : {
      40                 :            :     ImplKeyData*    mpNext;
      41                 :            :     rtl::OString maKey;
      42                 :            :     rtl::OString maValue;
      43                 :            :     sal_Bool            mbIsComment;
      44                 :            : };
      45                 :            : 
      46                 :       1552 : struct ImplGroupData
      47                 :            : {
      48                 :            :     ImplGroupData*  mpNext;
      49                 :            :     ImplKeyData*    mpFirstKey;
      50                 :            :     rtl::OString maGroupName;
      51                 :            :     sal_uInt16          mnEmptyLines;
      52                 :            : };
      53                 :            : 
      54                 :       1264 : struct ImplConfigData
      55                 :            : {
      56                 :            :     ImplGroupData*  mpFirstGroup;
      57                 :            :     rtl::OUString   maFileName;
      58                 :            :     sal_uIntPtr         mnDataUpdateId;
      59                 :            :     sal_uIntPtr         mnTimeStamp;
      60                 :            :     LineEnd         meLineEnd;
      61                 :            :     sal_uInt16          mnRefCount;
      62                 :            :     sal_Bool            mbModified;
      63                 :            :     sal_Bool            mbRead;
      64                 :            :     sal_Bool            mbIsUTF8BOM;
      65                 :            : };
      66                 :            : 
      67                 :        632 : static String toUncPath( const String& rPath )
      68                 :            : {
      69                 :        632 :     ::rtl::OUString aFileURL;
      70                 :            : 
      71                 :            :     // check if rFileName is already a URL; if not make it so
      72 [ +  + ][ +  - ]:        632 :     if( rPath.CompareToAscii( "file://", 7 ) == COMPARE_EQUAL )
      73         [ +  - ]:        316 :         aFileURL = rPath;
      74 [ +  - ][ +  - ]:        316 :     else if( ::osl::FileBase::getFileURLFromSystemPath( rPath, aFileURL ) != ::osl::FileBase::E_None )
                 [ -  + ]
      75         [ #  # ]:          0 :         aFileURL = rPath;
      76                 :            : 
      77         [ +  - ]:        632 :     return aFileURL;
      78                 :            : }
      79                 :            : 
      80                 :        618 : static sal_uIntPtr ImplSysGetConfigTimeStamp( const rtl::OUString& rFileName )
      81                 :            : {
      82                 :        618 :     sal_uIntPtr nTimeStamp = 0;
      83                 :        618 :     ::osl::DirectoryItem aItem;
      84                 :        618 :     ::osl::FileStatus aStatus( osl_FileStatus_Mask_ModifyTime );
      85                 :            : 
      86 [ +  - ][ +  - ]:       1236 :     if( ::osl::DirectoryItem::get( rFileName, aItem ) == ::osl::FileBase::E_None &&
         [ +  - ][ +  - ]
      87         [ +  - ]:        618 :         aItem.getFileStatus( aStatus ) == ::osl::FileBase::E_None )
      88                 :            :     {
      89         [ +  - ]:        618 :         nTimeStamp = aStatus.getModifyTime().Seconds;
      90                 :            :     }
      91                 :            : 
      92         [ +  - ]:        618 :     return nTimeStamp;
      93                 :            : }
      94                 :            : 
      95                 :        632 : static sal_uInt8* ImplSysReadConfig( const rtl::OUString& rFileName,
      96                 :            :                                 sal_uInt64& rRead, sal_Bool& rbRead, sal_Bool& rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
      97                 :            : {
      98                 :        632 :     sal_uInt8*          pBuf = NULL;
      99                 :        632 :     ::osl::File aFile( rFileName );
     100                 :            : 
     101 [ +  + ][ +  - ]:        632 :     if( aFile.open( osl_File_OpenFlag_Read ) == ::osl::FileBase::E_None )
     102                 :            :     {
     103                 :        460 :         sal_uInt64 nPos = 0;
     104 [ +  - ][ +  - ]:        460 :         if( aFile.getSize( nPos ) == ::osl::FileBase::E_None )
     105                 :            :         {
     106         [ -  + ]:        460 :             if (nPos > std::numeric_limits< std::size_t >::max()) {
     107         [ #  # ]:          0 :                 aFile.close();
     108                 :          0 :                 return 0;
     109                 :            :             }
     110         [ +  - ]:        460 :             pBuf = new sal_uInt8[static_cast< std::size_t >(nPos)];
     111                 :        460 :             sal_uInt64 nRead = 0;
     112 [ +  - ][ +  - ]:        460 :             if( aFile.read( pBuf, nPos, nRead ) == ::osl::FileBase::E_None && nRead == nPos )
         [ +  - ][ +  - ]
     113                 :            :             {
     114                 :            :                 //skip the byte-order-mark 0xEF 0xBB 0xBF, if it was UTF8 files
     115                 :        460 :                 unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
     116 [ +  + ][ -  + ]:        460 :                 if (nRead > 2 && memcmp(pBuf, BOM, 3) == 0)
     117                 :            :                 {
     118                 :          0 :                     nRead -= 3;
     119         [ #  # ]:          0 :                     rtl_moveMemory(pBuf, pBuf + 3, sal::static_int_cast<sal_Size>(nRead * sizeof(sal_uInt8)) );
     120                 :          0 :                     rbIsUTF8BOM = sal_True;
     121                 :            :                 }
     122                 :            : 
     123         [ +  - ]:        460 :                 rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
     124                 :        460 :                 rbRead = sal_True;
     125                 :        460 :                 rRead = nRead;
     126                 :            :             }
     127                 :            :             else
     128                 :            :             {
     129         [ #  # ]:          0 :                 delete[] pBuf;
     130                 :        460 :                 pBuf = NULL;
     131                 :            :             }
     132                 :            :         }
     133         [ +  - ]:        460 :         aFile.close();
     134                 :            :     }
     135                 :            : 
     136         [ +  - ]:        632 :     return pBuf;
     137                 :            : }
     138                 :            : 
     139                 :        158 : static sal_Bool ImplSysWriteConfig( const rtl::OUString& rFileName,
     140                 :            :                                 const sal_uInt8* pBuf, sal_uIntPtr nBufLen, sal_Bool rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
     141                 :            : {
     142                 :        158 :     sal_Bool bSuccess = sal_False;
     143                 :        158 :     sal_Bool bUTF8BOMSuccess = sal_False;
     144                 :            : 
     145                 :        158 :     ::osl::File aFile( rFileName );
     146         [ +  - ]:        158 :     ::osl::FileBase::RC eError = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
     147         [ +  - ]:        158 :     if( eError != ::osl::FileBase::E_None )
     148         [ +  - ]:        158 :         eError = aFile.open( osl_File_OpenFlag_Write );
     149         [ +  - ]:        158 :     if( eError == ::osl::FileBase::E_None )
     150                 :            :     {
     151                 :            :         // truncate
     152         [ +  - ]:        158 :         aFile.setSize( 0 );
     153                 :            :         sal_uInt64 nWritten;
     154                 :            : 
     155                 :            :         //write the the byte-order-mark 0xEF 0xBB 0xBF first , if it was UTF8 files
     156         [ -  + ]:        158 :         if ( rbIsUTF8BOM )
     157                 :            :         {
     158                 :          0 :             unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
     159                 :            :             sal_uInt64 nUTF8BOMWritten;
     160 [ #  # ][ #  # ]:          0 :             if( aFile.write( BOM, 3, nUTF8BOMWritten ) == ::osl::FileBase::E_None && 3 == nUTF8BOMWritten )
         [ #  # ][ #  # ]
     161                 :            :             {
     162                 :          0 :                 bUTF8BOMSuccess = sal_True;
     163                 :            :             }
     164                 :            :         }
     165                 :            : 
     166 [ +  - ][ +  - ]:        158 :         if( aFile.write( pBuf, nBufLen, nWritten ) == ::osl::FileBase::E_None && nWritten == nBufLen )
         [ +  - ][ +  - ]
     167                 :            :         {
     168                 :        158 :             bSuccess = sal_True;
     169                 :            :         }
     170 [ -  + ][ #  # ]:        158 :         if ( rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess )
         [ #  # ][ +  - ]
     171                 :            :         {
     172         [ +  - ]:        158 :             rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
     173                 :            :         }
     174                 :            :     }
     175                 :            : 
     176 [ -  + ][ #  # ]:        158 :     return rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess;
         [ #  # ][ +  - ]
     177                 :            : }
     178                 :            : 
     179                 :            : namespace {
     180                 :      21550 : rtl::OString makeOString(const sal_uInt8* p, sal_uInt64 n)
     181                 :            : {
     182         [ -  + ]:      21550 :     if (n > SAL_MAX_INT32)
     183                 :            :     {
     184                 :            :         #ifdef WNT
     185                 :            :         abort();
     186                 :            :         #else
     187                 :          0 :         ::std::abort(); //TODO: handle this gracefully
     188                 :            :         #endif
     189                 :            :     }
     190                 :            :     return rtl::OString(
     191                 :            :         reinterpret_cast< char const * >(p),
     192                 :      21550 :         sal::static_int_cast< sal_Int32 >(n));
     193                 :            : }
     194                 :            : }
     195                 :            : 
     196                 :        460 : static void ImplMakeConfigList( ImplConfigData* pData,
     197                 :            :                                 const sal_uInt8* pBuf, sal_uInt64 nLen )
     198                 :            : {
     199         [ +  + ]:        460 :     if ( !nLen )
     200                 :        460 :         return;
     201                 :            : 
     202                 :            :     // Parse buffer and build config list
     203                 :            :     sal_uInt64 nStart;
     204                 :            :     sal_uInt64 nLineLen;
     205                 :            :     sal_uInt64 nNameLen;
     206                 :            :     sal_uInt64 nKeyLen;
     207                 :            :     sal_uInt64 i;
     208                 :            :     const sal_uInt8*    pLine;
     209                 :        302 :     ImplKeyData*    pPrevKey = NULL;
     210                 :            :     ImplKeyData*    pKey;
     211                 :        302 :     ImplGroupData*  pPrevGroup = NULL;
     212                 :        302 :     ImplGroupData*  pGroup = NULL;
     213                 :        302 :     i = 0;
     214         [ +  + ]:      20588 :     while ( i < nLen )
     215                 :            :     {
     216                 :            :         // Ctrl+Z
     217         [ -  + ]:      20286 :         if ( pBuf[i] == 0x1A )
     218                 :          0 :             break;
     219                 :            : 
     220                 :            :         // Remove spaces and tabs
     221 [ +  - ][ -  + ]:      20286 :         while ( (pBuf[i] == ' ') || (pBuf[i] == '\t') )
                 [ -  + ]
     222                 :          0 :             i++;
     223                 :            : 
     224                 :            :         // remember line-starts
     225                 :      20286 :         nStart = i;
     226                 :      20286 :         pLine = pBuf+i;
     227                 :            : 
     228                 :            :         // search line-endings
     229 [ +  - ][ +  - ]:     767718 :         while (  (i < nLen) && pBuf[i] && (pBuf[i] != '\r') && (pBuf[i] != '\n') &&
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
     230                 :     747432 :                 (pBuf[i] != 0x1A) )
     231                 :     747432 :             i++;
     232                 :            : 
     233                 :      20286 :         nLineLen = i-nStart;
     234                 :            : 
     235                 :            :         // if Line-ending is found, continue once
     236 [ +  + ][ +  + ]:      20286 :         if ( (i+1 < nLen) &&
         [ +  - ][ -  + ]
     237                 :      39968 :              (pBuf[i] != pBuf[i+1]) &&
     238                 :      34208 :              ((pBuf[i+1] == '\r') || (pBuf[i+1] == '\n')) )
     239                 :          0 :             i++;
     240                 :      20286 :         i++;
     241                 :            : 
     242                 :            :         // evaluate line
     243         [ +  + ]:      20286 :         if ( *pLine == '[' )
     244                 :            :         {
     245                 :        446 :             pGroup               = new ImplGroupData;
     246                 :        446 :             pGroup->mpNext       = NULL;
     247                 :        446 :             pGroup->mpFirstKey   = NULL;
     248                 :        446 :             pGroup->mnEmptyLines = 0;
     249         [ +  + ]:        446 :             if ( pPrevGroup )
     250                 :        288 :                 pPrevGroup->mpNext = pGroup;
     251                 :            :             else
     252                 :        158 :                 pData->mpFirstGroup = pGroup;
     253                 :        446 :             pPrevGroup  = pGroup;
     254                 :        446 :             pPrevKey    = NULL;
     255                 :        446 :             pKey        = NULL;
     256                 :            : 
     257                 :            :             // filter group names
     258                 :        446 :             pLine++;
     259                 :        446 :             nLineLen--;
     260                 :            :             // remove spaces and tabs
     261 [ +  - ][ -  + ]:        446 :             while ( (*pLine == ' ') || (*pLine == '\t') )
                 [ -  + ]
     262                 :            :             {
     263                 :          0 :                 nLineLen--;
     264                 :          0 :                 pLine++;
     265                 :            :             }
     266                 :        446 :             nNameLen = 0;
     267 [ +  - ][ +  + ]:       7916 :             while ( (nNameLen < nLineLen) && (pLine[nNameLen] != ']') )
                 [ +  + ]
     268                 :       7470 :                 nNameLen++;
     269         [ +  - ]:        446 :             if ( nNameLen )
     270                 :            :             {
     271 [ +  - ][ -  + ]:        446 :                 while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
                 [ -  + ]
     272                 :          0 :                     nNameLen--;
     273                 :            :             }
     274                 :        446 :             pGroup->maGroupName = makeOString(pLine, nNameLen);
     275                 :            :         }
     276                 :            :         else
     277                 :            :         {
     278         [ +  + ]:      19840 :             if ( nLineLen )
     279                 :            :             {
     280                 :            :                 // If no group exists yet, add to default
     281         [ +  + ]:      16960 :                 if ( !pGroup )
     282                 :            :                 {
     283                 :        144 :                     pGroup              = new ImplGroupData;
     284                 :        144 :                     pGroup->mpNext      = NULL;
     285                 :        144 :                     pGroup->mpFirstKey  = NULL;
     286                 :        144 :                     pGroup->mnEmptyLines = 0;
     287         [ -  + ]:        144 :                     if ( pPrevGroup )
     288                 :          0 :                         pPrevGroup->mpNext = pGroup;
     289                 :            :                     else
     290                 :        144 :                         pData->mpFirstGroup = pGroup;
     291                 :        144 :                     pPrevGroup  = pGroup;
     292                 :        144 :                     pPrevKey    = NULL;
     293                 :            :                 }
     294                 :            : 
     295                 :            :                 // if empty line, append it
     296         [ +  + ]:      16960 :                 if ( pPrevKey )
     297                 :            :                 {
     298         [ +  + ]:      18962 :                     while ( pGroup->mnEmptyLines )
     299                 :            :                     {
     300                 :       2592 :                         pKey                = new ImplKeyData;
     301                 :       2592 :                         pKey->mbIsComment   = sal_True;
     302                 :       2592 :                         pPrevKey->mpNext    = pKey;
     303                 :       2592 :                         pPrevKey            = pKey;
     304                 :       2592 :                         pGroup->mnEmptyLines--;
     305                 :            :                     }
     306                 :            :                 }
     307                 :            : 
     308                 :            :                 // Generate new key
     309                 :      16960 :                 pKey        = new ImplKeyData;
     310                 :      16960 :                 pKey->mpNext = NULL;
     311         [ +  + ]:      16960 :                 if ( pPrevKey )
     312                 :      16370 :                     pPrevKey->mpNext = pKey;
     313                 :            :                 else
     314                 :        590 :                     pGroup->mpFirstKey = pKey;
     315                 :      16960 :                 pPrevKey = pKey;
     316         [ +  + ]:      16960 :                 if ( pLine[0] == ';' )
     317                 :            :                 {
     318                 :      12384 :                     pKey->maValue = makeOString(pLine, nLineLen);
     319                 :      12384 :                     pKey->mbIsComment = sal_True;
     320                 :            :                 }
     321                 :            :                 else
     322                 :            :                 {
     323                 :       4576 :                     pKey->mbIsComment = sal_False;
     324                 :       4576 :                     nNameLen = 0;
     325 [ +  - ][ +  + ]:      76262 :                     while ( (nNameLen < nLineLen) && (pLine[nNameLen] != '=') )
                 [ +  + ]
     326                 :      71686 :                         nNameLen++;
     327                 :       4576 :                     nKeyLen = nNameLen;
     328                 :            :                     // Remove spaces and tabs
     329         [ +  - ]:       4576 :                     if ( nNameLen )
     330                 :            :                     {
     331 [ +  - ][ -  + ]:       4576 :                         while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
                 [ -  + ]
     332                 :          0 :                             nNameLen--;
     333                 :            :                     }
     334                 :       4576 :                     pKey->maKey = makeOString(pLine, nNameLen);
     335                 :       4576 :                     nKeyLen++;
     336         [ +  + ]:       4576 :                     if ( nKeyLen < nLineLen )
     337                 :            :                     {
     338                 :       4144 :                         pLine += nKeyLen;
     339                 :       4144 :                         nLineLen -= nKeyLen;
     340                 :            :                         // Remove spaces and tabs
     341 [ +  - ][ -  + ]:       4144 :                         while ( (*pLine == ' ') || (*pLine == '\t') )
                 [ -  + ]
     342                 :            :                         {
     343                 :          0 :                             nLineLen--;
     344                 :          0 :                             pLine++;
     345                 :            :                         }
     346         [ +  - ]:       4144 :                         if ( nLineLen )
     347                 :            :                         {
     348 [ +  - ][ -  + ]:       4144 :                             while ( (pLine[nLineLen-1] == ' ') || (pLine[nLineLen-1] == '\t') )
                 [ -  + ]
     349                 :          0 :                                 nLineLen--;
     350                 :       4144 :                             pKey->maValue = makeOString(pLine, nLineLen);
     351                 :            :                         }
     352                 :            :                     }
     353                 :            :                 }
     354                 :            :             }
     355                 :            :             else
     356                 :            :             {
     357                 :            :                 // Spaces are counted and appended only after key generation,
     358                 :            :                 // as we want to store spaces even after adding new keys
     359         [ +  - ]:       2880 :                 if ( pGroup )
     360                 :       2880 :                     pGroup->mnEmptyLines++;
     361                 :            :             }
     362                 :            :         }
     363                 :            :     }
     364                 :            : }
     365                 :            : 
     366                 :        158 : static sal_uInt8* ImplGetConfigBuffer( const ImplConfigData* pData, sal_uIntPtr& rLen )
     367                 :            : {
     368                 :            :     sal_uInt8*      pWriteBuf;
     369                 :            :     sal_uInt8*      pBuf;
     370                 :        158 :     sal_uInt8       aLineEndBuf[2] = {0, 0};
     371                 :            :     ImplKeyData*    pKey;
     372                 :            :     ImplGroupData*  pGroup;
     373                 :            :     unsigned int    nBufLen;
     374                 :            :     sal_uInt32      nValueLen;
     375                 :            :     sal_uInt32      nKeyLen;
     376                 :            :     sal_uInt32      nLineEndLen;
     377                 :            : 
     378         [ -  + ]:        158 :     if ( pData->meLineEnd == LINEEND_CR )
     379                 :            :     {
     380                 :          0 :         aLineEndBuf[0] = _CR;
     381                 :          0 :         nLineEndLen = 1;
     382                 :            :     }
     383         [ -  + ]:        158 :     else if ( pData->meLineEnd == LINEEND_LF )
     384                 :            :     {
     385                 :          0 :         aLineEndBuf[0] = _LF;
     386                 :          0 :         nLineEndLen = 1;
     387                 :            :     }
     388                 :            :     else
     389                 :            :     {
     390                 :        158 :         aLineEndBuf[0] = _CR;
     391                 :        158 :         aLineEndBuf[1] = _LF;
     392                 :        158 :         nLineEndLen = 2;
     393                 :            :     }
     394                 :            : 
     395                 :        158 :     nBufLen = 0;
     396                 :        158 :     pGroup = pData->mpFirstGroup;
     397         [ +  + ]:        316 :     while ( pGroup )
     398                 :            :     {
     399                 :            :         // Don't write empty groups
     400         [ +  - ]:        158 :         if ( pGroup->mpFirstKey )
     401                 :            :         {
     402                 :        158 :             nBufLen += pGroup->maGroupName.getLength() + nLineEndLen + 2;
     403                 :        158 :             pKey = pGroup->mpFirstKey;
     404         [ +  + ]:        948 :             while ( pKey )
     405                 :            :             {
     406                 :        790 :                 nValueLen = pKey->maValue.getLength();
     407         [ -  + ]:        790 :                 if ( pKey->mbIsComment )
     408                 :          0 :                     nBufLen += nValueLen + nLineEndLen;
     409                 :            :                 else
     410                 :        790 :                     nBufLen += pKey->maKey.getLength() + nValueLen + nLineEndLen + 1;
     411                 :            : 
     412                 :        790 :                 pKey = pKey->mpNext;
     413                 :            :             }
     414                 :            : 
     415                 :            :             // Write empty lines after each group
     416         [ -  + ]:        158 :             if ( !pGroup->mnEmptyLines )
     417                 :          0 :                 pGroup->mnEmptyLines = 1;
     418                 :        158 :             nBufLen += nLineEndLen * pGroup->mnEmptyLines;
     419                 :            :         }
     420                 :            : 
     421                 :        158 :         pGroup = pGroup->mpNext;
     422                 :            :     }
     423                 :            : 
     424                 :            :     // Output buffer length
     425                 :        158 :     rLen = nBufLen;
     426         [ -  + ]:        158 :     if ( !nBufLen )
     427                 :            :     {
     428         [ #  # ]:          0 :         pWriteBuf = new sal_uInt8[nLineEndLen];
     429         [ #  # ]:          0 :         if ( pWriteBuf )
     430                 :            :         {
     431                 :          0 :             pWriteBuf[0] = aLineEndBuf[0];
     432         [ #  # ]:          0 :             if ( nLineEndLen == 2 )
     433                 :          0 :                 pWriteBuf[1] = aLineEndBuf[1];
     434                 :          0 :             return pWriteBuf;
     435                 :            :         }
     436                 :            :         else
     437                 :          0 :             return 0;
     438                 :            :     }
     439                 :            : 
     440                 :            :     // Allocate new write buffer (caller frees it)
     441         [ +  - ]:        158 :     pWriteBuf = new sal_uInt8[nBufLen];
     442         [ -  + ]:        158 :     if ( !pWriteBuf )
     443                 :          0 :         return 0;
     444                 :            : 
     445                 :            :     // fill buffer
     446                 :        158 :     pBuf = pWriteBuf;
     447                 :        158 :     pGroup = pData->mpFirstGroup;
     448         [ +  + ]:        316 :     while ( pGroup )
     449                 :            :     {
     450                 :            :         // Don't write empty groups
     451         [ +  - ]:        158 :         if ( pGroup->mpFirstKey )
     452                 :            :         {
     453                 :        158 :             *pBuf = '[';    pBuf++;
     454                 :        158 :             memcpy( pBuf, pGroup->maGroupName.getStr(), pGroup->maGroupName.getLength() );
     455                 :        158 :             pBuf += pGroup->maGroupName.getLength();
     456                 :        158 :             *pBuf = ']';    pBuf++;
     457                 :        158 :             *pBuf = aLineEndBuf[0]; pBuf++;
     458         [ +  - ]:        158 :             if ( nLineEndLen == 2 )
     459                 :            :             {
     460                 :        158 :                 *pBuf = aLineEndBuf[1]; pBuf++;
     461                 :            :             }
     462                 :        158 :             pKey = pGroup->mpFirstKey;
     463         [ +  + ]:        948 :             while ( pKey )
     464                 :            :             {
     465                 :        790 :                 nValueLen = pKey->maValue.getLength();
     466         [ -  + ]:        790 :                 if ( pKey->mbIsComment )
     467                 :            :                 {
     468         [ #  # ]:          0 :                     if ( nValueLen )
     469                 :            :                     {
     470                 :          0 :                         memcpy( pBuf, pKey->maValue.getStr(), nValueLen );
     471                 :          0 :                         pBuf += nValueLen;
     472                 :            :                     }
     473                 :          0 :                     *pBuf = aLineEndBuf[0]; pBuf++;
     474         [ #  # ]:          0 :                     if ( nLineEndLen == 2 )
     475                 :            :                     {
     476                 :          0 :                         *pBuf = aLineEndBuf[1]; pBuf++;
     477                 :            :                     }
     478                 :            :                 }
     479                 :            :                 else
     480                 :            :                 {
     481                 :        790 :                     nKeyLen = pKey->maKey.getLength();
     482                 :        790 :                     memcpy( pBuf, pKey->maKey.getStr(), nKeyLen );
     483                 :        790 :                     pBuf += nKeyLen;
     484                 :        790 :                     *pBuf = '=';    pBuf++;
     485                 :        790 :                     memcpy( pBuf, pKey->maValue.getStr(), nValueLen );
     486                 :        790 :                     pBuf += nValueLen;
     487                 :        790 :                     *pBuf = aLineEndBuf[0]; pBuf++;
     488         [ +  - ]:        790 :                     if ( nLineEndLen == 2 )
     489                 :            :                     {
     490                 :        790 :                         *pBuf = aLineEndBuf[1]; pBuf++;
     491                 :            :                     }
     492                 :            :                 }
     493                 :            : 
     494                 :        790 :                 pKey = pKey->mpNext;
     495                 :            :             }
     496                 :            : 
     497                 :            :             // Store empty line after each group
     498                 :        158 :             sal_uInt16 nEmptyLines = pGroup->mnEmptyLines;
     499         [ +  + ]:        316 :             while ( nEmptyLines )
     500                 :            :             {
     501                 :        158 :                 *pBuf = aLineEndBuf[0]; pBuf++;
     502         [ +  - ]:        158 :                 if ( nLineEndLen == 2 )
     503                 :            :                 {
     504                 :        158 :                     *pBuf = aLineEndBuf[1]; pBuf++;
     505                 :            :                 }
     506                 :        158 :                 nEmptyLines--;
     507                 :            :             }
     508                 :            :         }
     509                 :            : 
     510                 :        158 :         pGroup = pGroup->mpNext;
     511                 :            :     }
     512                 :            : 
     513                 :        158 :     return pWriteBuf;
     514                 :            : }
     515                 :            : 
     516                 :        632 : static void ImplReadConfig( ImplConfigData* pData )
     517                 :            : {
     518                 :        632 :     sal_uIntPtr nTimeStamp = 0;
     519                 :        632 :     sal_uInt64  nRead = 0;
     520                 :        632 :     sal_Bool    bRead = sal_False;
     521                 :        632 :     sal_Bool    bIsUTF8BOM =sal_False;
     522         [ +  - ]:        632 :     sal_uInt8*  pBuf = ImplSysReadConfig( pData->maFileName, nRead, bRead, bIsUTF8BOM, nTimeStamp );
     523                 :            : 
     524                 :            :     // Read config list from buffer
     525         [ +  + ]:        632 :     if ( pBuf )
     526                 :            :     {
     527         [ +  - ]:        460 :         ImplMakeConfigList( pData, pBuf, nRead );
     528         [ +  - ]:        460 :         delete[] pBuf;
     529                 :            :     }
     530                 :        632 :     pData->mnTimeStamp = nTimeStamp;
     531                 :        632 :     pData->mbModified  = sal_False;
     532         [ +  + ]:        632 :     if ( bRead )
     533                 :        460 :         pData->mbRead = sal_True;
     534         [ -  + ]:        632 :     if ( bIsUTF8BOM )
     535                 :          0 :         pData->mbIsUTF8BOM = sal_True;
     536                 :        632 : }
     537                 :            : 
     538                 :        158 : static void ImplWriteConfig( ImplConfigData* pData )
     539                 :            : {
     540                 :            : #ifdef DBG_UTIL
     541                 :            :     if ( DbgIsAssert() )
     542                 :            :     {
     543                 :            :         if ( pData->mnTimeStamp != ImplSysGetConfigTimeStamp( pData->maFileName ) )
     544                 :            :         {
     545                 :            :             OSL_TRACE( "Config overwrites modified configfile:\n %s", rtl::OUStringToOString(pData->maFileName, RTL_TEXTENCODING_UTF8).getStr() );
     546                 :            :         }
     547                 :            :     }
     548                 :            : #endif
     549                 :            : 
     550                 :            :     // Read config list from buffer
     551                 :            :     sal_uIntPtr nBufLen;
     552         [ +  - ]:        158 :     sal_uInt8*  pBuf = ImplGetConfigBuffer( pData, nBufLen );
     553         [ +  - ]:        158 :     if ( pBuf )
     554                 :            :     {
     555 [ +  - ][ +  - ]:        158 :         if ( ImplSysWriteConfig( pData->maFileName, pBuf, nBufLen, pData->mbIsUTF8BOM, pData->mnTimeStamp ) )
     556                 :        158 :             pData->mbModified = sal_False;
     557         [ +  - ]:        158 :         delete[] pBuf;
     558                 :            :     }
     559                 :            :     else
     560                 :          0 :         pData->mbModified = sal_False;
     561                 :        158 : }
     562                 :            : 
     563                 :        632 : static void ImplDeleteConfigData( ImplConfigData* pData )
     564                 :            : {
     565                 :            :     ImplKeyData*    pTempKey;
     566                 :            :     ImplKeyData*    pKey;
     567                 :            :     ImplGroupData*  pTempGroup;
     568                 :        632 :     ImplGroupData*  pGroup = pData->mpFirstGroup;
     569         [ +  + ]:       1408 :     while ( pGroup )
     570                 :            :     {
     571                 :        776 :         pTempGroup = pGroup->mpNext;
     572                 :            : 
     573                 :            :         // remove all keys
     574                 :        776 :         pKey = pGroup->mpFirstKey;
     575         [ +  + ]:      21118 :         while ( pKey )
     576                 :            :         {
     577                 :      20342 :             pTempKey = pKey->mpNext;
     578         [ +  - ]:      20342 :             delete pKey;
     579                 :      20342 :             pKey = pTempKey;
     580                 :            :         }
     581                 :            : 
     582                 :            :         // remove group and continue
     583         [ +  - ]:        776 :         delete pGroup;
     584                 :        776 :         pGroup = pTempGroup;
     585                 :            :     }
     586                 :            : 
     587                 :        632 :     pData->mpFirstGroup = NULL;
     588                 :        632 : }
     589                 :            : 
     590                 :        632 : static ImplConfigData* ImplGetConfigData( const rtl::OUString& rFileName )
     591                 :            : {
     592                 :            :     ImplConfigData* pData;
     593                 :            : 
     594                 :        632 :     pData                   = new ImplConfigData;
     595                 :        632 :     pData->maFileName       = rFileName;
     596                 :        632 :     pData->mpFirstGroup     = NULL;
     597                 :        632 :     pData->mnDataUpdateId   = 0;
     598                 :        632 :     pData->meLineEnd        = LINEEND_CRLF;
     599                 :        632 :     pData->mnRefCount       = 0;
     600                 :        632 :     pData->mbRead           = sal_False;
     601                 :        632 :     pData->mbIsUTF8BOM      = sal_False;
     602                 :        632 :     ImplReadConfig( pData );
     603                 :            : 
     604                 :        632 :     return pData;
     605                 :            : }
     606                 :            : 
     607                 :        632 : static void ImplFreeConfigData( ImplConfigData* pDelData )
     608                 :            : {
     609                 :        632 :     ImplDeleteConfigData( pDelData );
     610         [ +  - ]:        632 :     delete pDelData;
     611                 :        632 : }
     612                 :            : 
     613                 :          0 : sal_Bool Config::ImplUpdateConfig() const
     614                 :            : {
     615                 :            :     // Re-read file if timestamp differs
     616         [ #  # ]:          0 :     if ( mpData->mnTimeStamp != ImplSysGetConfigTimeStamp( maFileName ) )
     617                 :            :     {
     618                 :          0 :         ImplDeleteConfigData( mpData );
     619                 :          0 :         ImplReadConfig( mpData );
     620                 :          0 :         mpData->mnDataUpdateId++;
     621                 :          0 :         return sal_True;
     622                 :            :     }
     623                 :            :     else
     624                 :          0 :         return sal_False;
     625                 :            : }
     626                 :            : 
     627                 :       7456 : ImplGroupData* Config::ImplGetGroup() const
     628                 :            : {
     629 [ +  + ][ +  + ]:       7456 :     if ( !mpActGroup || (mnDataUpdateId != mpData->mnDataUpdateId) )
     630                 :            :     {
     631                 :        632 :         ImplGroupData* pPrevGroup = NULL;
     632                 :        632 :         ImplGroupData* pGroup = mpData->mpFirstGroup;
     633         [ +  + ]:        920 :         while ( pGroup )
     634                 :            :         {
     635         [ +  + ]:        734 :             if ( pGroup->maGroupName.equalsIgnoreAsciiCase(maGroupName) )
     636                 :        446 :                 break;
     637                 :            : 
     638                 :        288 :             pPrevGroup = pGroup;
     639                 :        288 :             pGroup = pGroup->mpNext;
     640                 :            :         }
     641                 :            : 
     642                 :            :         // Add group if not exists
     643         [ +  + ]:        632 :         if ( !pGroup )
     644                 :            :         {
     645                 :        186 :             pGroup               = new ImplGroupData;
     646                 :        186 :             pGroup->mpNext       = NULL;
     647                 :        186 :             pGroup->mpFirstKey   = NULL;
     648                 :        186 :             pGroup->mnEmptyLines = 1;
     649         [ -  + ]:        186 :             if ( pPrevGroup )
     650                 :          0 :                 pPrevGroup->mpNext = pGroup;
     651                 :            :             else
     652                 :        186 :                 mpData->mpFirstGroup = pGroup;
     653                 :            :         }
     654                 :            : 
     655                 :            :         // Always inherit group names and upate cache members
     656                 :        632 :         pGroup->maGroupName             = maGroupName;
     657                 :        632 :         ((Config*)this)->mnDataUpdateId = mpData->mnDataUpdateId;
     658                 :        632 :         ((Config*)this)->mpActGroup     = pGroup;
     659                 :            :     }
     660                 :            : 
     661                 :       7456 :     return mpActGroup;
     662                 :            : }
     663                 :            : 
     664                 :        632 : Config::Config( const rtl::OUString& rFileName )
     665                 :            : {
     666                 :            :     // Initialize config data
     667 [ +  - ][ +  - ]:        632 :     maFileName      = toUncPath( rFileName );
         [ +  - ][ +  - ]
                 [ +  - ]
     668         [ +  - ]:        632 :     mpData          = ImplGetConfigData( maFileName );
     669                 :        632 :     mpActGroup      = NULL;
     670                 :        632 :     mnDataUpdateId  = 0;
     671                 :        632 :     mnLockCount     = 1;
     672                 :        632 :     mbPersistence   = sal_True;
     673                 :            : 
     674                 :            : #ifdef DBG_UTIL
     675                 :            :     rtl::OStringBuffer aTraceStr(
     676                 :            :         RTL_CONSTASCII_STRINGPARAM("Config::Config( "));
     677                 :            :     aTraceStr.append(rtl::OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
     678                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" )"));
     679                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
     680                 :            : #endif
     681                 :        632 : }
     682                 :            : 
     683                 :        632 : Config::~Config()
     684                 :            : {
     685                 :            : #ifdef DBG_UTIL
     686                 :            :     OSL_TRACE( "Config::~Config()" );
     687                 :            : #endif
     688                 :            : 
     689         [ +  - ]:        632 :     Flush();
     690                 :        632 :     ImplFreeConfigData( mpData );
     691                 :        632 : }
     692                 :            : 
     693                 :        632 : void Config::SetGroup(const rtl::OString& rGroup)
     694                 :            : {
     695                 :            :     // If group is to be reset, it needs to be updated on next call
     696         [ +  + ]:        632 :     if ( maGroupName != rGroup )
     697                 :            :     {
     698                 :        560 :         maGroupName     = rGroup;
     699                 :        560 :         mnDataUpdateId  = mpData->mnDataUpdateId-1;
     700                 :            :     }
     701                 :        632 : }
     702                 :            : 
     703                 :          0 : void Config::DeleteGroup(const rtl::OString& rGroup)
     704                 :            : {
     705                 :            :     // Update config data if necessary
     706 [ #  # ][ #  # ]:          0 :     if ( !mnLockCount || !mpData->mbRead )
     707                 :            :     {
     708                 :          0 :         ImplUpdateConfig();
     709                 :          0 :         mpData->mbRead = sal_True;
     710                 :            :     }
     711                 :            : 
     712                 :          0 :     ImplGroupData* pPrevGroup = NULL;
     713                 :          0 :     ImplGroupData* pGroup = mpData->mpFirstGroup;
     714         [ #  # ]:          0 :     while ( pGroup )
     715                 :            :     {
     716         [ #  # ]:          0 :         if ( pGroup->maGroupName.equalsIgnoreAsciiCase(rGroup) )
     717                 :          0 :             break;
     718                 :            : 
     719                 :          0 :         pPrevGroup = pGroup;
     720                 :          0 :         pGroup = pGroup->mpNext;
     721                 :            :     }
     722                 :            : 
     723         [ #  # ]:          0 :     if ( pGroup )
     724                 :            :     {
     725                 :            :         // Remove all keys
     726                 :            :         ImplKeyData* pTempKey;
     727                 :          0 :         ImplKeyData* pKey = pGroup->mpFirstKey;
     728         [ #  # ]:          0 :         while ( pKey )
     729                 :            :         {
     730                 :          0 :             pTempKey = pKey->mpNext;
     731         [ #  # ]:          0 :             delete pKey;
     732                 :          0 :             pKey = pTempKey;
     733                 :            :         }
     734                 :            : 
     735                 :            :         // Rewire pointers and remove group
     736         [ #  # ]:          0 :         if ( pPrevGroup )
     737                 :          0 :             pPrevGroup->mpNext = pGroup->mpNext;
     738                 :            :         else
     739                 :          0 :             mpData->mpFirstGroup = pGroup->mpNext;
     740         [ #  # ]:          0 :         delete pGroup;
     741                 :            : 
     742                 :            :         // Rewrite config data
     743 [ #  # ][ #  # ]:          0 :         if ( !mnLockCount && mbPersistence )
     744                 :          0 :             ImplWriteConfig( mpData );
     745                 :            :         else
     746                 :            :         {
     747                 :          0 :             mpData->mbModified = sal_True;
     748                 :            :         }
     749                 :            : 
     750                 :          0 :         mnDataUpdateId = mpData->mnDataUpdateId;
     751                 :          0 :         mpData->mnDataUpdateId++;
     752                 :            :     }
     753                 :          0 : }
     754                 :            : 
     755                 :        288 : rtl::OString Config::GetGroupName(sal_uInt16 nGroup) const
     756                 :            : {
     757                 :            :     // Update config data if necessary
     758         [ -  + ]:        288 :     if ( !mnLockCount )
     759                 :          0 :         ImplUpdateConfig();
     760                 :            : 
     761                 :        288 :     ImplGroupData*  pGroup = mpData->mpFirstGroup;
     762                 :        288 :     sal_uInt16          nGroupCount = 0;
     763                 :        288 :     rtl::OString aGroupName;
     764         [ +  - ]:        648 :     while ( pGroup )
     765                 :            :     {
     766         [ +  + ]:        648 :         if ( nGroup == nGroupCount )
     767                 :            :         {
     768                 :        288 :             aGroupName = pGroup->maGroupName;
     769                 :        288 :             break;
     770                 :            :         }
     771                 :            : 
     772                 :        360 :         nGroupCount++;
     773                 :        360 :         pGroup = pGroup->mpNext;
     774                 :            :     }
     775                 :            : 
     776                 :        288 :     return aGroupName;
     777                 :            : }
     778                 :            : 
     779                 :        360 : sal_uInt16 Config::GetGroupCount() const
     780                 :            : {
     781                 :            :     // Update config data if necessary
     782         [ -  + ]:        360 :     if ( !mnLockCount )
     783                 :          0 :         ImplUpdateConfig();
     784                 :            : 
     785                 :        360 :     ImplGroupData*  pGroup = mpData->mpFirstGroup;
     786                 :        360 :     sal_uInt16          nGroupCount = 0;
     787         [ +  + ]:       1224 :     while ( pGroup )
     788                 :            :     {
     789                 :        864 :         nGroupCount++;
     790                 :        864 :         pGroup = pGroup->mpNext;
     791                 :            :     }
     792                 :            : 
     793                 :        360 :     return nGroupCount;
     794                 :            : }
     795                 :            : 
     796                 :        144 : sal_Bool Config::HasGroup(const rtl::OString& rGroup) const
     797                 :            : {
     798                 :            :     // Update config data if necessary
     799         [ -  + ]:        144 :     if ( !mnLockCount )
     800                 :          0 :         ImplUpdateConfig();
     801                 :            : 
     802                 :        144 :     ImplGroupData*  pGroup = mpData->mpFirstGroup;
     803                 :        144 :     sal_Bool            bRet = sal_False;
     804                 :            : 
     805         [ +  + ]:        216 :     while( pGroup )
     806                 :            :     {
     807         [ +  + ]:        144 :         if( pGroup->maGroupName.equalsIgnoreAsciiCase(rGroup) )
     808                 :            :         {
     809                 :         72 :             bRet = sal_True;
     810                 :         72 :             break;
     811                 :            :         }
     812                 :            : 
     813                 :         72 :         pGroup = pGroup->mpNext;
     814                 :            :     }
     815                 :            : 
     816                 :        144 :     return bRet;
     817                 :            : }
     818                 :            : 
     819                 :       3110 : rtl::OString Config::ReadKey(const rtl::OString& rKey) const
     820                 :            : {
     821         [ +  - ]:       3110 :     return ReadKey(rKey, rtl::OString());
     822                 :            : }
     823                 :            : 
     824                 :          0 : rtl::OUString Config::ReadKey(const rtl::OString& rKey, rtl_TextEncoding eEncoding) const
     825                 :            : {
     826         [ #  # ]:          0 :     if ( mpData->mbIsUTF8BOM )
     827                 :          0 :         eEncoding = RTL_TEXTENCODING_UTF8;
     828         [ #  # ]:          0 :     return rtl::OStringToOUString(ReadKey(rKey), eEncoding);
     829                 :            : }
     830                 :            : 
     831                 :       3182 : rtl::OString Config::ReadKey(const rtl::OString& rKey, const rtl::OString& rDefault) const
     832                 :            : {
     833                 :            : #ifdef DBG_UTIL
     834                 :            :     rtl::OStringBuffer aTraceStr(
     835                 :            :         RTL_CONSTASCII_STRINGPARAM("Config::ReadKey( "));
     836                 :            :     aTraceStr.append(rKey);
     837                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" ) from "));
     838                 :            :     aTraceStr.append(GetGroup());
     839                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" in "));
     840                 :            :     aTraceStr.append(rtl::OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
     841                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
     842                 :            : #endif
     843                 :            : 
     844                 :            :     // Update config data if necessary
     845         [ -  + ]:       3182 :     if ( !mnLockCount )
     846                 :          0 :         ImplUpdateConfig();
     847                 :            : 
     848                 :            :     // Search key, return value if found
     849                 :       3182 :     ImplGroupData* pGroup = ImplGetGroup();
     850         [ +  - ]:       3182 :     if ( pGroup )
     851                 :            :     {
     852                 :       3182 :         ImplKeyData* pKey = pGroup->mpFirstKey;
     853         [ +  + ]:     144990 :         while ( pKey )
     854                 :            :         {
     855 [ +  + ][ +  + ]:     143464 :             if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
                 [ +  + ]
     856                 :       1656 :                 return pKey->maValue;
     857                 :            : 
     858                 :     141808 :             pKey = pKey->mpNext;
     859                 :            :         }
     860                 :            :     }
     861                 :            : 
     862                 :       3182 :     return rDefault;
     863                 :            : }
     864                 :            : 
     865                 :        790 : void Config::WriteKey(const rtl::OString& rKey, const rtl::OString& rStr)
     866                 :            : {
     867                 :            : #ifdef DBG_UTIL
     868                 :            :     rtl::OStringBuffer aTraceStr(RTL_CONSTASCII_STRINGPARAM("Config::WriteKey( "));
     869                 :            :     aTraceStr.append(rKey);
     870                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(", "));
     871                 :            :     aTraceStr.append(rStr);
     872                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" ) to "));
     873                 :            :     aTraceStr.append(GetGroup());
     874                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" in "));
     875                 :            :     aTraceStr.append(rtl::OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
     876                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
     877                 :            : #endif
     878                 :            : 
     879                 :            :     // Update config data if necessary
     880 [ +  - ][ -  + ]:        790 :     if ( !mnLockCount || !mpData->mbRead )
     881                 :            :     {
     882                 :          0 :         ImplUpdateConfig();
     883                 :          0 :         mpData->mbRead = sal_True;
     884                 :            :     }
     885                 :            : 
     886                 :            :     // Search key and update value if found
     887                 :        790 :     ImplGroupData* pGroup = ImplGetGroup();
     888         [ +  - ]:        790 :     if ( pGroup )
     889                 :            :     {
     890                 :        790 :         ImplKeyData* pPrevKey = NULL;
     891                 :        790 :         ImplKeyData* pKey = pGroup->mpFirstKey;
     892         [ +  + ]:       2370 :         while ( pKey )
     893                 :            :         {
     894 [ +  - ][ -  + ]:       1580 :             if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
                 [ -  + ]
     895                 :          0 :                 break;
     896                 :            : 
     897                 :       1580 :             pPrevKey = pKey;
     898                 :       1580 :             pKey = pKey->mpNext;
     899                 :            :         }
     900                 :            : 
     901                 :            :         sal_Bool bNewValue;
     902         [ +  - ]:        790 :         if ( !pKey )
     903                 :            :         {
     904                 :        790 :             pKey              = new ImplKeyData;
     905                 :        790 :             pKey->mpNext      = NULL;
     906                 :        790 :             pKey->maKey       = rKey;
     907                 :        790 :             pKey->mbIsComment = sal_False;
     908         [ +  + ]:        790 :             if ( pPrevKey )
     909                 :        632 :                 pPrevKey->mpNext = pKey;
     910                 :            :             else
     911                 :        158 :                 pGroup->mpFirstKey = pKey;
     912                 :        790 :             bNewValue = sal_True;
     913                 :            :         }
     914                 :            :         else
     915                 :          0 :             bNewValue = pKey->maValue != rStr;
     916                 :            : 
     917         [ +  - ]:        790 :         if ( bNewValue )
     918                 :            :         {
     919                 :        790 :             pKey->maValue = rStr;
     920                 :            : 
     921 [ #  # ][ -  + ]:        790 :             if ( !mnLockCount && mbPersistence )
     922                 :          0 :                 ImplWriteConfig( mpData );
     923                 :            :             else
     924                 :            :             {
     925                 :        790 :                 mpData->mbModified = sal_True;
     926                 :            :             }
     927                 :            :         }
     928                 :            :     }
     929                 :        790 : }
     930                 :            : 
     931                 :          0 : void Config::DeleteKey(const rtl::OString& rKey)
     932                 :            : {
     933                 :            :     // Update config data if necessary
     934 [ #  # ][ #  # ]:          0 :     if ( !mnLockCount || !mpData->mbRead )
     935                 :            :     {
     936                 :          0 :         ImplUpdateConfig();
     937                 :          0 :         mpData->mbRead = sal_True;
     938                 :            :     }
     939                 :            : 
     940                 :            :     // Search key and update value
     941                 :          0 :     ImplGroupData* pGroup = ImplGetGroup();
     942         [ #  # ]:          0 :     if ( pGroup )
     943                 :            :     {
     944                 :          0 :         ImplKeyData* pPrevKey = NULL;
     945                 :          0 :         ImplKeyData* pKey = pGroup->mpFirstKey;
     946         [ #  # ]:          0 :         while ( pKey )
     947                 :            :         {
     948 [ #  # ][ #  # ]:          0 :             if ( !pKey->mbIsComment && pKey->maKey.equalsIgnoreAsciiCase(rKey) )
                 [ #  # ]
     949                 :          0 :                 break;
     950                 :            : 
     951                 :          0 :             pPrevKey = pKey;
     952                 :          0 :             pKey = pKey->mpNext;
     953                 :            :         }
     954                 :            : 
     955         [ #  # ]:          0 :         if ( pKey )
     956                 :            :         {
     957                 :            :             // Rewire group pointers and delete
     958         [ #  # ]:          0 :             if ( pPrevKey )
     959                 :          0 :                 pPrevKey->mpNext = pKey->mpNext;
     960                 :            :             else
     961                 :          0 :                 pGroup->mpFirstKey = pKey->mpNext;
     962         [ #  # ]:          0 :             delete pKey;
     963                 :            : 
     964                 :            :             // Rewrite config file
     965 [ #  # ][ #  # ]:          0 :             if ( !mnLockCount && mbPersistence )
     966                 :          0 :                 ImplWriteConfig( mpData );
     967                 :            :             else
     968                 :            :             {
     969                 :          0 :                 mpData->mbModified = sal_True;
     970                 :            :             }
     971                 :            :         }
     972                 :            :     }
     973                 :          0 : }
     974                 :            : 
     975                 :       1828 : sal_uInt16 Config::GetKeyCount() const
     976                 :            : {
     977                 :            : #ifdef DBG_UTIL
     978                 :            :     rtl::OStringBuffer aTraceStr(
     979                 :            :         RTL_CONSTASCII_STRINGPARAM("Config::GetKeyCount()"));
     980                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" from "));
     981                 :            :     aTraceStr.append(GetGroup());
     982                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" in "));
     983                 :            :     aTraceStr.append(rtl::OUStringToOString(maFileName, RTL_TEXTENCODING_UTF8));
     984                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
     985                 :            : #endif
     986                 :            : 
     987                 :            :     // Update config data if necessary
     988         [ -  + ]:       1828 :     if ( !mnLockCount )
     989                 :          0 :         ImplUpdateConfig();
     990                 :            : 
     991                 :            :     // Search key and update value
     992                 :       1828 :     sal_uInt16 nCount = 0;
     993                 :       1828 :     ImplGroupData* pGroup = ImplGetGroup();
     994         [ +  - ]:       1828 :     if ( pGroup )
     995                 :            :     {
     996                 :       1828 :         ImplKeyData* pKey = pGroup->mpFirstKey;
     997         [ +  + ]:      98668 :         while ( pKey )
     998                 :            :         {
     999         [ +  + ]:      96840 :             if ( !pKey->mbIsComment )
    1000                 :      21600 :                 nCount++;
    1001                 :            : 
    1002                 :      96840 :             pKey = pKey->mpNext;
    1003                 :            :         }
    1004                 :            :     }
    1005                 :            : 
    1006                 :       1828 :     return nCount;
    1007                 :            : }
    1008                 :            : 
    1009                 :       1656 : rtl::OString Config::GetKeyName(sal_uInt16 nKey) const
    1010                 :            : {
    1011                 :            : #ifdef DBG_UTIL
    1012                 :            :     rtl::OStringBuffer aTraceStr(
    1013                 :            :         RTL_CONSTASCII_STRINGPARAM("Config::GetKeyName( "));
    1014                 :            :     aTraceStr.append(static_cast<sal_Int32>(nKey));
    1015                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" ) from "));
    1016                 :            :     aTraceStr.append(GetGroup());
    1017                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" in "));
    1018                 :            :     aTraceStr.append(rtl::OUStringToOString(
    1019                 :            :         maFileName, RTL_TEXTENCODING_UTF8));
    1020                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
    1021                 :            : #endif
    1022                 :            : 
    1023                 :            :     // search key and return name if found
    1024                 :       1656 :     ImplGroupData* pGroup = ImplGetGroup();
    1025         [ +  - ]:       1656 :     if ( pGroup )
    1026                 :            :     {
    1027                 :       1656 :         ImplKeyData* pKey = pGroup->mpFirstKey;
    1028         [ +  - ]:      69696 :         while ( pKey )
    1029                 :            :         {
    1030         [ +  + ]:      69696 :             if ( !pKey->mbIsComment )
    1031                 :            :             {
    1032         [ +  + ]:      10800 :                 if ( !nKey )
    1033                 :       1656 :                     return pKey->maKey;
    1034                 :       9144 :                 nKey--;
    1035                 :            :             }
    1036                 :            : 
    1037                 :      68040 :             pKey = pKey->mpNext;
    1038                 :            :         }
    1039                 :            :     }
    1040                 :            : 
    1041                 :       1656 :     return rtl::OString();
    1042                 :            : }
    1043                 :            : 
    1044                 :          0 : rtl::OString Config::ReadKey(sal_uInt16 nKey) const
    1045                 :            : {
    1046                 :            : #ifdef DBG_UTIL
    1047                 :            :     rtl::OStringBuffer aTraceStr(
    1048                 :            :         RTL_CONSTASCII_STRINGPARAM("Config::ReadKey( "));
    1049                 :            :     aTraceStr.append(static_cast<sal_Int32>(nKey));
    1050                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" ) from "));
    1051                 :            :     aTraceStr.append(GetGroup());
    1052                 :            :     aTraceStr.append(RTL_CONSTASCII_STRINGPARAM(" in "));
    1053                 :            :     aTraceStr.append(rtl::OUStringToOString(maFileName,
    1054                 :            :         RTL_TEXTENCODING_UTF8));
    1055                 :            :     OSL_TRACE("%s", aTraceStr.getStr());
    1056                 :            : #endif
    1057                 :            : 
    1058                 :            :     // Search key and return value if found
    1059                 :          0 :     ImplGroupData* pGroup = ImplGetGroup();
    1060         [ #  # ]:          0 :     if ( pGroup )
    1061                 :            :     {
    1062                 :          0 :         ImplKeyData* pKey = pGroup->mpFirstKey;
    1063         [ #  # ]:          0 :         while ( pKey )
    1064                 :            :         {
    1065         [ #  # ]:          0 :             if ( !pKey->mbIsComment )
    1066                 :            :             {
    1067         [ #  # ]:          0 :                 if ( !nKey )
    1068                 :          0 :                     return pKey->maValue;
    1069                 :          0 :                 nKey--;
    1070                 :            :             }
    1071                 :            : 
    1072                 :          0 :             pKey = pKey->mpNext;
    1073                 :            :         }
    1074                 :            :     }
    1075                 :            : 
    1076                 :          0 :     return rtl::OString();
    1077                 :            : }
    1078                 :            : 
    1079                 :        790 : void Config::Flush()
    1080                 :            : {
    1081 [ +  + ][ +  - ]:        790 :     if ( mpData->mbModified && mbPersistence )
    1082                 :        158 :         ImplWriteConfig( mpData );
    1083                 :        790 : }
    1084                 :            : 
    1085                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10