//------------------------------------------------------------------------------ // Desc: Class to support reading/writing/parsing .ini files // // Tabs: 3 // // Copyright (c) 2002-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: inifile.cpp 3115 2006-01-19 13:24:39 -0700 (Thu, 19 Jan 2006) dsanders $ //------------------------------------------------------------------------------ #include "ftksys.h" /**************************************************************************** Desc: ****************************************************************************/ typedef struct INI_LINE { char * pszParamName; char * pszParamValue; char * pszComment; struct INI_LINE * pPrev; struct INI_LINE * pNext; } INI_LINE; /**************************************************************************** Desc: ****************************************************************************/ class F_IniFile : public IF_IniFile { public: F_IniFile(); virtual ~F_IniFile(); void init( void); RCODE FLMAPI read( const char * pszFileName); RCODE FLMAPI write( void); FLMBOOL FLMAPI getParam( const char * pszParamName, FLMUINT * puiParamVal); FLMBOOL FLMAPI getParam( const char * pszParamName, FLMBOOL * pbParamVal); FLMBOOL FLMAPI getParam( const char * pszParamName, char ** ppszParamVal); RCODE FLMAPI setParam( const char * pszParamName, FLMUINT uiParamVal); RCODE FLMAPI setParam( const char * pszParamName, FLMBOOL bParamVal); RCODE FLMAPI setParam( const char * pszParamName, const char * pszParamVal); FINLINE FLMBOOL FLMAPI testParam( const char * pszParamName) { if( findParam( pszParamName)) { return( TRUE); } return( FALSE); } private: RCODE readLine( char * pucBuf, FLMUINT * puiBytes, FLMBOOL * pbMore); RCODE parseBuffer( char * pucBuf, FLMUINT uiNumButes); INI_LINE * findParam( const char * pszParamName); RCODE setParamCommon( INI_LINE ** ppLine, const char * pszParamName); void fromAscii( FLMUINT * puiVal, const char * pszParamValue); void fromAscii( FLMBOOL * pbVal, const char * pszParamValue); RCODE toAscii( char ** ppszParamValue, FLMUINT puiVal); RCODE toAscii( char ** ppszParamValue, FLMBOOL pbVal); RCODE toAscii( char ** ppszParamValue, const char * pszVal); FINLINE FLMBOOL isWhiteSpace( FLMBYTE ucChar) { return( ucChar == 32 || ucChar == 9 ? TRUE : FALSE); } F_Pool m_pool; IF_FileHdl * m_pFileHdl; char * m_pszFileName; INI_LINE * m_pFirstLine; INI_LINE * m_pLastLine; FLMBOOL m_bReady; FLMBOOL m_bModified; FLMUINT m_uiFileOffset; }; /**************************************************************************** Desc: ****************************************************************************/ F_IniFile::F_IniFile() { m_pFirstLine = NULL; m_pLastLine = NULL; m_bReady = FALSE; m_bModified = FALSE; m_pszFileName = NULL; m_pFileHdl = NULL; m_pool.poolInit( 512); } /**************************************************************************** Desc: ****************************************************************************/ F_IniFile::~F_IniFile() { if( m_pszFileName) { f_free( &m_pszFileName); } m_pool.poolFree(); if( m_pFileHdl) { m_pFileHdl->Release(); } } /**************************************************************************** Desc: ****************************************************************************/ RCODE FLMAPI FlmAllocIniFile( IF_IniFile ** ppIniFile) { RCODE rc = NE_FLM_OK; F_IniFile * pIniFile = NULL; if( (pIniFile = f_new F_IniFile) == NULL) { rc = RC_SET( NE_FLM_MEM); goto Exit; } pIniFile->init(); *ppIniFile = pIniFile; pIniFile = NULL; Exit: if( pIniFile) { pIniFile->Release(); } return( rc); } /**************************************************************************** Desc: ****************************************************************************/ void F_IniFile::init( void) { m_pool.poolFree(); m_pool.poolInit( 512); m_pFirstLine = NULL; m_pLastLine = NULL; m_bReady = TRUE; } /**************************************************************************** Desc: Read the ini file and parse its contents ****************************************************************************/ RCODE FLMAPI F_IniFile::read( const char * pszFileName) { RCODE rc = NE_FLM_OK; FLMBOOL bMore = FALSE; FLMBOOL bEOF = FALSE; #define INITIAL_READ_BUF_SIZE 100 FLMUINT uiReadBufSize = 0; FLMUINT uiBytesAvail = 0; FLMUINT uiBytesInLine = 0; char * pszReadBuf = NULL; FLMUINT uiLineNum = 0; IF_FileSystem * pFileSystem = f_getFileSysPtr(); f_assert( m_bReady); f_assert( !m_pFileHdl); // Open the file if (RC_BAD( rc = f_alloc( f_strlen( pszFileName) + 1, &m_pszFileName))) { goto Exit; } f_strcpy( m_pszFileName, pszFileName); // It's not an error if the file doesn't exist. If it does exist, // we'll read in its data. if( RC_BAD( pFileSystem->openFile( pszFileName, FLM_IO_RDONLY, &m_pFileHdl))) { goto Exit; } m_uiFileOffset = 0; // Read in and parse the file uiReadBufSize = INITIAL_READ_BUF_SIZE; if (RC_BAD( rc = f_alloc( uiReadBufSize, &pszReadBuf))) { goto Exit; } // Read in and parse each line in the file... while (!bEOF) { uiLineNum++; uiBytesAvail = uiReadBufSize; if( RC_BAD( rc = readLine( pszReadBuf, &uiBytesAvail, &bMore)) && rc != NE_FLM_IO_END_OF_FILE) { goto Exit; } if (rc == NE_FLM_IO_END_OF_FILE) { bEOF = TRUE; } // While there are more bytes in the line, re-alloc the buffer, and do // another read. uiBytesInLine = uiBytesAvail; while( bMore) { uiBytesAvail = uiReadBufSize; uiReadBufSize *= 2; if (RC_BAD( rc = f_realloc( uiReadBufSize, &pszReadBuf))) { goto Exit; } if (RC_BAD( rc = readLine( pszReadBuf+uiBytesAvail, &uiBytesAvail, &bMore)) && (rc != NE_FLM_IO_END_OF_FILE) ) { goto Exit; } if( rc == NE_FLM_IO_END_OF_FILE) { bEOF = TRUE; } uiBytesInLine += uiBytesAvail; } if ( (RC_OK( rc) || (rc == NE_FLM_IO_END_OF_FILE)) && (uiBytesInLine > 0) ) { // NumBytes will be 0 if the line was blank. No need // to call parseBuffer in this case if (RC_BAD( rc = parseBuffer( pszReadBuf, uiBytesInLine))) { if (rc == NE_FLM_SYNTAX) { rc = NE_FLM_OK; } else { goto Exit; } } } } Exit: // Close the file if( m_pFileHdl) { m_pFileHdl->close(); m_pFileHdl->Release(); m_pFileHdl = NULL; } // Free the buffer if (pszReadBuf) { f_free( &pszReadBuf); } if (rc == NE_FLM_IO_END_OF_FILE) { rc = NE_FLM_OK; } return rc; } /**************************************************************************** Desc: Copies the data stored in the INI_LINE structs to the ini file ****************************************************************************/ RCODE FLMAPI F_IniFile::write( void) { RCODE rc = NE_FLM_OK; FLMUINT uiBytesWritten; INI_LINE * pCurLine = NULL; FLMBOOL uiFileOffset = 0; IF_FileSystem * pFileSystem = f_getFileSysPtr(); f_assert( m_bReady); if (!m_bModified) { // Nothing needs to be written goto Exit; } // Open the file f_assert( !m_pFileHdl); if (RC_BAD( rc = pFileSystem->createFile( m_pszFileName, FLM_IO_RDWR, &m_pFileHdl))) { goto Exit; } pCurLine = m_pFirstLine; while (pCurLine) { if (pCurLine->pszParamName) { // Output the param name if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, f_strlen( pCurLine->pszParamName), pCurLine->pszParamName, &uiBytesWritten))) { goto Exit; } uiFileOffset += uiBytesWritten; if (pCurLine->pszParamValue) { // Output the "=" and the value if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, 1, (void *)"=", &uiBytesWritten))) { goto Exit; } uiFileOffset += uiBytesWritten; if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, f_strlen( pCurLine->pszParamValue), pCurLine->pszParamValue, &uiBytesWritten))) { goto Exit; } uiFileOffset += uiBytesWritten; } } if (pCurLine->pszComment) { // Output the comment if (pCurLine->pszParamName) { if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, 2, (void *)" #", &uiBytesWritten))) { goto Exit; } } else { if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, 1, (void *)"#", &uiBytesWritten))) { goto Exit; } } uiFileOffset += uiBytesWritten; if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, f_strlen( pCurLine->pszComment), pCurLine->pszComment, &uiBytesWritten))) { goto Exit; } uiFileOffset += uiBytesWritten; } // Write out a newline... if (RC_BAD (rc = m_pFileHdl->write( uiFileOffset, f_strlen( "\n"), (void *)"\n", &uiBytesWritten))) { goto Exit; } uiFileOffset += uiBytesWritten; pCurLine = pCurLine->pNext; } m_bModified = FALSE; Exit: if (m_pFileHdl) { m_pFileHdl->close(); m_pFileHdl->Release(); m_pFileHdl = NULL; } return( rc); } /**************************************************************************** Desc: Retrieves the value associated with the specified name from the list of INI_STRUCTs ****************************************************************************/ FLMBOOL FLMAPI F_IniFile::getParam( const char * pszParamName, FLMUINT * puiParamVal) { FLMBOOL bFound = FALSE; INI_LINE * pLine = NULL; f_assert( m_bReady); pLine = findParam( pszParamName); if( !pLine) { goto Exit; } if( !pLine->pszParamValue) { goto Exit; } fromAscii( puiParamVal, pLine->pszParamValue); bFound = TRUE; Exit: return( bFound); } /**************************************************************************** Desc: Stores a new value for the specified name (or creates a new name/value pair) in the list of INI_STRUCTs ****************************************************************************/ RCODE FLMAPI F_IniFile::setParam( const char * pszParamName, FLMUINT uiParamVal) { RCODE rc = NE_FLM_OK; INI_LINE * pLine; f_assert( m_bReady); // If the parameter exists in the list, just store the new value. // Othewise, create a new INI_LINE and add it to the list pLine = findParam( pszParamName); if( !pLine) { if (RC_BAD( rc = setParamCommon( &pLine, pszParamName))) { goto Exit; } } if( RC_BAD( rc = toAscii( &pLine->pszParamValue, uiParamVal))) { goto Exit; } Exit: return( rc); } /**************************************************************************** Desc: Retrieves the value associated with the specified name from the list of INI_STRUCTs ****************************************************************************/ FLMBOOL FLMAPI F_IniFile::getParam( const char * pszParamName, FLMBOOL * pbParamVal) // Out: The value associated with name { FLMBOOL bFound = FALSE; INI_LINE * pLine = NULL; f_assert( m_bReady); pLine = findParam( pszParamName); if( !pLine) { goto Exit; } if( !pLine->pszParamValue) { goto Exit; } fromAscii( pbParamVal, pLine->pszParamValue); bFound = TRUE; Exit: return( bFound); } /**************************************************************************** Desc: Stores a new value for the specified name (or creates a new name/value pair) in the list of INI_STRUCTs ****************************************************************************/ RCODE FLMAPI F_IniFile::setParam( const char * pszParamName, FLMBOOL bParamVal) { RCODE rc = NE_FLM_OK; INI_LINE * pLine; f_assert( m_bReady); // If the parameter exists in the list, just store the new value. // Othewise, create a new INI_LINE and add it to the list pLine = findParam( pszParamName); if( !pLine) { if (RC_BAD( rc = setParamCommon( &pLine, pszParamName))) { goto Exit; } } if( RC_BAD( rc = toAscii( &pLine->pszParamValue, bParamVal))) { goto Exit; } Exit: return( rc); } /**************************************************************************** Desc: Retrieves the value associated with the specified name from the list of INI_STRUCTs ****************************************************************************/ FLMBOOL FLMAPI F_IniFile::getParam( const char * pszParamName, char ** ppszParamVal) { FLMBOOL bFound = FALSE; INI_LINE * pLine = NULL; f_assert( m_bReady); *ppszParamVal = NULL; pLine = findParam( pszParamName); if( !pLine) { goto Exit; } if( pLine->pszParamValue == NULL) { goto Exit; } *ppszParamVal = pLine->pszParamValue; bFound = TRUE; Exit: return( bFound); } /**************************************************************************** Desc: Stores a new value for the specified name (or creates a new name/value pair) in the list of INI_STRUCTs ****************************************************************************/ RCODE FLMAPI F_IniFile::setParam( const char * pszParamName, const char * pszParamVal) { RCODE rc = NE_FLM_OK; INI_LINE * pLine; f_assert( m_bReady); // If the parameter exists in the list, just store the new value. // Othewise, create a new INI_LINE and add it to the list pLine = findParam( pszParamName); if( !pLine) { if( RC_BAD( rc = setParamCommon( &pLine, pszParamName))) { goto Exit; } } if( RC_BAD( rc = toAscii( &pLine->pszParamValue, pszParamVal))) { goto Exit; } Exit: return( rc); } /**************************************************************************** Desc: Read a line from the ini file and store it in pszBuf ****************************************************************************/ RCODE F_IniFile::readLine( char * pszBuf, FLMUINT * puiBytes, FLMBOOL * pbMore) { RCODE rc = NE_FLM_OK; FLMUINT uiBytesRead = 0; FLMUINT uiBytesInLine = 0; FLMUINT uiEOLBytes = 0; FLMBOOL bEOL = FALSE; f_assert( m_pFileHdl); rc = m_pFileHdl->read( m_uiFileOffset, *puiBytes, (FLMBYTE *)pszBuf, &uiBytesRead); if ( RC_OK( rc) || rc == NE_FLM_IO_END_OF_FILE) { // Check to see if we got more than one line... while( !bEOL && (uiBytesInLine < uiBytesRead) ) { if( pszBuf[ uiBytesInLine] == 13 || pszBuf[ uiBytesInLine] == 10) { // NOTE: If we end up reading the first byte of a CR/LF pair, but // but the second byte is read on the next call, then it will get // counted as a new (but empty) line. We're not going to worry // about it though, because empty lines end up getting ignored // and this isn't likely to happen often enough to effect // performance. bEOL = TRUE; *puiBytes = uiBytesInLine; uiEOLBytes=1; // Check for a CR/LF pair (or a LF/CR pair...) if( (uiBytesInLine + 1 < uiBytesRead) && (pszBuf[ uiBytesInLine + 1] == 13 || pszBuf[ uiBytesInLine + 1] == 10)) { uiEOLBytes++; } } else { uiBytesInLine++; } } // Set the file position variable forward appropriately... m_uiFileOffset += uiBytesInLine + uiEOLBytes; } // If we read in more than one line, then don't want to return // NE_FLM_IO_END_OF_FILE... if( rc == NE_FLM_IO_END_OF_FILE && (uiBytesInLine + uiEOLBytes) < uiBytesRead) { rc = NE_FLM_OK; } // Last step - update pbMore *pbMore = (bEOL || (uiBytesRead == 0)) ? FALSE : TRUE; return( rc); } /**************************************************************************** Desc: Parse a single line from the ini file into its name, value and comment parts. ****************************************************************************/ RCODE F_IniFile::parseBuffer( char * pszBuf, FLMUINT uiNumBytes) { RCODE rc = NE_FLM_OK; FLMUINT uiCurrentChar = 0; char * pszNameStart = NULL; char * pszNameEnd = NULL; char * pszValStart = NULL; char * pszValEnd = NULL; char * pszCommentStart = NULL; INI_LINE * pLine = NULL; FLMUINT uiStrLen = 0; f_assert( pszBuf); f_assert( uiNumBytes); // Start looking for the parameter name... while (uiCurrentChar < uiNumBytes) { if( !isWhiteSpace( pszBuf[uiCurrentChar])) { if (pszBuf[uiCurrentChar] == '#') { goto Comment; } else { pszNameStart = &pszBuf[uiCurrentChar]; break; } } uiCurrentChar++; } // We've found a param name, now mark the end of it // We determine the end by looking for whitespace or '=' // or '#' while (uiCurrentChar < uiNumBytes) { if( isWhiteSpace( pszBuf[uiCurrentChar]) || (pszBuf[uiCurrentChar] == '=') || (pszBuf[uiCurrentChar] == '#')) { pszNameEnd = &pszBuf[uiCurrentChar-1]; break; } uiCurrentChar++; } if( (uiCurrentChar == uiNumBytes) && (pszNameEnd == NULL) ) { pszNameEnd = &pszBuf[uiCurrentChar - 1]; } // Now, there may be a value part or a comment part next. If there's a // value, it had better be preceeded by an '=' while( (uiCurrentChar < uiNumBytes) && isWhiteSpace( pszBuf[uiCurrentChar]) ) { uiCurrentChar++; } if( uiCurrentChar < uiNumBytes && pszBuf[ uiCurrentChar] == '#') { goto Comment; } if( uiCurrentChar < uiNumBytes && pszBuf[uiCurrentChar] != '=' ) { rc = RC_SET( NE_FLM_SYNTAX); goto Exit; } // Ok - at this point pszBuf[uiCurrentChar] contains an =. Skip over // the = and any whitespace that follows. while( uiCurrentChar < uiNumBytes) { uiCurrentChar++; if( !isWhiteSpace( pszBuf[uiCurrentChar])) { pszValStart = &pszBuf[uiCurrentChar]; break; } } // Now mark the end of the value. // We determine the end by looking for whitespace or '#' while( uiCurrentChar < uiNumBytes) { if( isWhiteSpace( pszBuf[uiCurrentChar]) || (pszBuf[uiCurrentChar] == '#')) { pszValEnd = &pszBuf[uiCurrentChar-1]; break; } uiCurrentChar++; } if( uiCurrentChar == uiNumBytes && !pszValEnd) { pszValEnd = &pszBuf[uiCurrentChar-1]; } Comment: // Check out the rest of the line to see if there's a comment while( uiCurrentChar < uiNumBytes) { if( !isWhiteSpace( pszBuf[ uiCurrentChar]) && pszBuf[ uiCurrentChar] != '#') { rc = RC_SET( NE_FLM_SYNTAX); goto Exit; } else if( pszBuf[ uiCurrentChar] == '#') { // Comment found. Set pszCommentStart to the next char pszCommentStart = &pszBuf[uiCurrentChar+1]; break; } uiCurrentChar++; } // Done parsing. Now, assuming the line had any info in it, // store all the strings... if( pszNameStart || pszCommentStart) { if( RC_BAD( rc = m_pool.poolCalloc( sizeof( INI_LINE), (void **)&pLine))) { goto Exit; } if( pszNameStart) { uiStrLen = pszNameEnd - pszNameStart + 1; if( RC_BAD( rc = m_pool.poolAlloc( uiStrLen + 1, (void **)&pLine->pszParamName))) { goto Exit; } f_memcpy( pLine->pszParamName, pszNameStart, uiStrLen); pLine->pszParamName[uiStrLen] = '\0'; } if( pszValStart) { uiStrLen = pszValEnd - pszValStart + 1; if( RC_BAD( rc = m_pool.poolAlloc( uiStrLen + 1, (void **)&pLine->pszParamValue))) { goto Exit; } f_memcpy(pLine->pszParamValue, pszValStart, uiStrLen); pLine->pszParamValue[uiStrLen] = '\0'; } if (pszCommentStart) { uiStrLen = uiNumBytes-(pszCommentStart-pszBuf); if (RC_BAD( rc = m_pool.poolAlloc( uiStrLen + 1, (void **)&pLine->pszComment))) { goto Exit; } f_memcpy(pLine->pszComment, pszCommentStart, uiStrLen); pLine->pszComment[uiStrLen] = '\0'; } // Insert this struct into the linked list if( m_pLastLine) { m_pLastLine->pNext = pLine; } pLine->pPrev = m_pLastLine; pLine->pNext = NULL; m_pLastLine = pLine; if( !m_pFirstLine) { m_pFirstLine = pLine; } } Exit: return( rc); } /**************************************************************************** Desc: Search through the list of INI_STRUCTs for a particular name ****************************************************************************/ INI_LINE * F_IniFile::findParam( const char * pszParamName) { INI_LINE * pCurLine = m_pFirstLine; while( pCurLine) { if (pCurLine->pszParamName) { if (f_strcmp( pszParamName, pCurLine->pszParamName) == 0) { return pCurLine; } } pCurLine = pCurLine->pNext; } return( NULL); } /**************************************************************************** Desc: This code is common to all of the SetParam() functions ****************************************************************************/ RCODE F_IniFile::setParamCommon( INI_LINE ** ppLine, const char * pszParamName) { RCODE rc = NE_FLM_OK; INI_LINE * pLine; if( RC_BAD( rc = m_pool.poolCalloc( sizeof( INI_LINE), (void **)&pLine))) { goto Exit; } if( m_pLastLine) { m_pLastLine->pNext = pLine; } pLine->pPrev = m_pLastLine; m_pLastLine = pLine; if( !m_pFirstLine) { m_pFirstLine = pLine; } if( RC_BAD( rc = m_pool.poolAlloc( f_strlen(pszParamName)+1, (void **)&pLine->pszParamName))) { goto Exit; } f_strcpy( pLine->pszParamName, pszParamName); Exit: if( RC_OK( rc)) { *ppLine = pLine; } return( rc); } /**************************************************************************** Desc: All of the fromAscii() functions convert values stored in strings to various native formats ****************************************************************************/ void F_IniFile::fromAscii( FLMUINT * puiVal, const char * pszBuf) { FLMUINT uiValue; FLMBOOL bAllowHex = FALSE; if( *pszBuf == '0' && (*(pszBuf + 1) == 'x' || *(pszBuf + 1) == 'X')) { pszBuf += 2; bAllowHex = TRUE; } uiValue = 0; while( *pszBuf) { if( *pszBuf >= '0' && *pszBuf <= '9') { if( !bAllowHex) { uiValue *= 10; } else { uiValue <<= 4; } uiValue += (FLMUINT)(*pszBuf - '0'); } else if( bAllowHex) { if( *pszBuf >= 'A' && *pszBuf <= 'F') { uiValue <<= 4; uiValue += (FLMUINT)(*pszBuf - 'A') + 10; } else if( *pszBuf >= 'a' && *pszBuf <= 'f') { uiValue <<= 4; uiValue += (FLMUINT)(*pszBuf - 'a') + 10; } else { break; } } else { break; } pszBuf++; } *puiVal = uiValue; } /**************************************************************************** Desc: All of the fromAscii() functions convert values stored in strings to various native formats ****************************************************************************/ void F_IniFile::fromAscii( FLMBOOL * pbVal, const char * pszParamValue) { if( f_stricmp( pszParamValue, "true") == 0 || f_stricmp( pszParamValue, "enabled") == 0 || f_stricmp( pszParamValue, "on") == 0 || f_stricmp( pszParamValue, "1") == 0) { *pbVal = TRUE; } else { *pbVal = FALSE; } } /**************************************************************************** Desc: All of the toAscii() functions convert values from their native formats to a string representation ****************************************************************************/ RCODE F_IniFile::toAscii( char ** ppszParamValue, FLMUINT puiVal) { RCODE rc = NE_FLM_OK; char szTemp[ 50]; f_sprintf( szTemp, "%*.*lu", sizeof(szTemp), sizeof(szTemp), puiVal); if( RC_BAD( rc = m_pool.poolAlloc( f_strlen( szTemp), (void **)ppszParamValue))) { goto Exit; } f_strcpy( *ppszParamValue, szTemp); m_bModified = TRUE; Exit: return( rc); } /**************************************************************************** Desc: All of the toAscii() functions convert values from their native formats to a string representation ****************************************************************************/ RCODE F_IniFile::toAscii( char ** ppszParamValue, FLMBOOL bVal) { RCODE rc = NE_FLM_OK; if( RC_BAD( rc = m_pool.poolAlloc( 6, (void **)ppszParamValue))) { goto Exit; } if( bVal) { f_memcpy( *ppszParamValue, "TRUE ", 6); } else { f_memcpy( *ppszParamValue, "FALSE", 6); } m_bModified = TRUE; Exit: return( rc); } /**************************************************************************** Desc: All of the toAscii() functions convert values from their native formats to a string representation ****************************************************************************/ RCODE F_IniFile::toAscii( char ** ppszParamValue, const char * pszVal) { RCODE rc = NE_FLM_OK; if( RC_BAD( rc = m_pool.poolAlloc( f_strlen( pszVal), (void **)ppszParamValue))) { goto Exit; } f_strcpy( *ppszParamValue, pszVal); m_bModified = TRUE; Exit: return( rc); }