diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b7d5394702..27675b9d9f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,19 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-10-13 00:21 UTC+0200 Francesco Saverio Giudice (info/at/fsgiudice.com) + * harbour/src/rtl/hbini.prg + * Changed hb_IniString() function name to hb_IniReadStr() + + Added hb_IniWriteStr() that returns a string from an Ini hash + hb_iniWriteStr( hIni, cCommentBegin, cCommentEnd, lAutoMain ) + -> cData | NIL + ! Fixed a previous error in logic in case of hIni with missing MAIN section + * harbour/include/hbextern.ch + - Removed hb_IniString() declaration + + Added hb_IniReadStr() and hb_IniWriteStr() external declarations + * harbour/tests/parseini.prg + + Added samples of hb_IniReadStr() and hb_IniWriteStr() functions + 2009-10-12 22:47 UTC+0200 Francesco Saverio Giudice (info/at/fsgiudice.com) * harbour/include/hbextern.ch + Added hb_IniString() external declaration diff --git a/harbour/include/hbextern.ch b/harbour/include/hbextern.ch index d4126729dc..97f80993be 100644 --- a/harbour/include/hbextern.ch +++ b/harbour/include/hbextern.ch @@ -943,8 +943,9 @@ EXTERNAL HB_SETCLSHANDLE EXTERNAL HB_INISETCOMMENT EXTERNAL HB_INIREAD -EXTERNAL HB_INISTRING +EXTERNAL HB_INIREADSTR EXTERNAL HB_INIWRITE +EXTERNAL HB_INIWRITESTR EXTERNAL HB_HRBRUN EXTERNAL HB_HRBDO diff --git a/harbour/src/rtl/hbini.prg b/harbour/src/rtl/hbini.prg index 200b1109fb..bea0d00a3f 100644 --- a/harbour/src/rtl/hbini.prg +++ b/harbour/src/rtl/hbini.prg @@ -104,9 +104,9 @@ FUNCTION hb_IniRead( cFileSpec, lKeyCaseSens, cSplitters, lAutoMain ) cData := hb_IniFileLow( cFileSpec ) - RETURN hb_IniString( cData, lKeyCaseSens, cSplitters, lAutoMain ) + RETURN hb_IniReadStr( cData, lKeyCaseSens, cSplitters, lAutoMain ) -FUNCTION hb_IniString( cData, lKeyCaseSens, cSplitters, lAutoMain ) +FUNCTION hb_IniReadStr( cData, lKeyCaseSens, cSplitters, lAutoMain ) LOCAL hIni := hb_Hash() /* Default case sensitiveness for keys */ @@ -162,6 +162,8 @@ STATIC FUNCTION hb_IniStringLow( hIni, cData, lKeyCaseSens, cSplitters, lAutoMai LOCAL cLine LOCAL reComment, reInclude, reSection, reSplitters + DEFAULT cData TO "" + reComment := hb_RegexComp( s_cHalfLineComment + "|^[ \t]*" + s_cLineComment ) reInclude := hb_RegexComp( "include (.*)" ) reSection := hb_RegexComp( "[[](.*)[]]" ) @@ -275,10 +277,15 @@ STATIC FUNCTION hb_IniStringLow( hIni, cData, lKeyCaseSens, cSplitters, lAutoMai FUNCTION hb_IniWrite( xFileName, hIni, cCommentBegin, cCommentEnd, lAutoMain ) LOCAL hFile LOCAL lClose - LOCAL cNewLine := hb_OSNewLine() - LOCAL cSection LOCAL cBuffer + cBuffer := hb_IniWriteStr( hIni, cCommentBegin, cCommentEnd, lAutoMain ) + + // if cBuffer == NIL I have to stop here + IF !ISCHARACTER( cBuffer ) + RETURN .F. + ENDIF + IF ISCHARACTER( xFileName ) hFile := FCreate( xFileName ) lClose := .T. @@ -293,30 +300,51 @@ FUNCTION hb_IniWrite( xFileName, hIni, cCommentBegin, cCommentEnd, lAutoMain ) RETURN .F. ENDIF - IF ! Empty( cCommentBegin ) - cBuffer := cCommentBegin + cNewLine - IF FWrite( hFile, cBuffer ) != Len( cBuffer ) - IF lClose - FClose( hFile ) - ENDIF - RETURN .F. + IF FWrite( hFile, cBuffer ) != Len( cBuffer ) + IF lClose + FClose( hFile ) ENDIF + RETURN .F. + ENDIF + + IF lClose + FClose( hFile ) + ENDIF + + RETURN .T. + +FUNCTION hb_IniWriteStr( hIni, cCommentBegin, cCommentEnd, lAutoMain ) + LOCAL cNewLine := hb_OSNewLine() + LOCAL cSection + LOCAL cBuffer := "" + + IF !HB_ISHASH( hIni ) + RETURN NIL + ENDIF + + IF ! Empty( cCommentBegin ) + cBuffer += cCommentBegin + cNewLine ENDIF DEFAULT lAutoMain TO .T. + // Fix if lAutoMain is .T. but I haven't a MAIN section + IF lAutoMain .AND. !hb_HHasKey( hIni, "MAIN" ) + lAutoMain := .F. + ENDIF + /* Write toplevel section */ IF lAutoMain /* When automain is on, write the main section */ hb_HEval( hIni[ "MAIN" ], ; - { |cKey, xVal| FWrite( hFile, hb_CStr( cKey ) + " = " + ; - hb_CStr( xVal ) + cNewLine ) } ) + { |cKey, xVal| cBuffer += hb_CStr( cKey ) + " = " + ; + hb_CStr( xVal ) + cNewLine } ) ELSE /* When automain is off, just write all the toplevel variables. */ hb_HEval( hIni, { |cKey, xVal| iif( ! hb_isHash( xVal ),; - FWrite( hFile, hb_CStr( cKey ) + " = " + ; - hb_CStr( xVal ) + cNewLine ), /* nothing */ ) } ) + cBuffer += hb_CStr( cKey ) + " = " + ; + hb_CStr( xVal ) + cNewLine, /* nothing */ ) } ) ENDIF FOR EACH cSection IN hIni @@ -334,31 +362,17 @@ FUNCTION hb_IniWrite( xFileName, hIni, cCommentBegin, cCommentEnd, lAutoMain ) ENDIF ENDIF - cBuffer := cNewLine + "[" + hb_CStr( cSection:__enumKey ) + "]" + cNewLine - IF FWrite( hFile, cBuffer ) != Len( cBuffer ) - IF lClose - FClose( hFile ) - ENDIF - RETURN .F. - ENDIF + cBuffer += cNewLine + "[" + hb_CStr( cSection:__enumKey ) + "]" + cNewLine hb_HEval( cSection, ; - { |cKey, xVal| FWrite( hFile, hb_CStr( cKey ) + "=" + ; - hb_CStr( xVal ) + cNewLine ) } ) + { |cKey, xVal| cBuffer += hb_CStr( cKey ) + "=" + ; + hb_CStr( xVal ) + cNewLine } ) NEXT IF ! Empty( cCommentEnd ) - cBuffer := cCommentEnd + cNewLine - IF FWrite( hFile, cBuffer ) != Len( cBuffer ) - IF lClose - FClose( hFile ) - ENDIF - RETURN .F. - ENDIF + cBuffer += cCommentEnd + cNewLine ENDIF - IF lClose - FClose( hFile ) - ENDIF + RETURN IIF( !Empty( cBuffer ), cBuffer, NIL ) + - RETURN .T. diff --git a/harbour/tests/parseini.prg b/harbour/tests/parseini.prg index bbfa40e10d..cb68dd79b5 100644 --- a/harbour/tests/parseini.prg +++ b/harbour/tests/parseini.prg @@ -9,7 +9,7 @@ * PROCEDURE Main( cName ) - LOCAL aIni, aSect + LOCAL hIni, aSect, cIni LOCAL cSection LOCAL cKey LOCAL nRow := 1 @@ -25,19 +25,19 @@ PROCEDURE Main( cName ) @nRow++, 5 SAY "Using default parseini.ini file" ENDIF - aIni := hb_IniRead( cName ) + hIni := hb_IniRead( cName ) @nRow, 0 ? "Content of " + cName - IF Empty( aIni ) + IF Empty( hIni ) ? "Not a valid .ini file!" ELSE - FOR EACH cSection IN aIni:Keys + FOR EACH cSection IN hIni:Keys ? ? "Section [" + cSection + "]" - aSect := aIni[ cSection ] + aSect := hIni[ cSection ] FOR EACH cKey IN aSect:Keys ? cKey + " = " + aSect[ cKey ] @@ -47,11 +47,11 @@ PROCEDURE Main( cName ) ? ? "Adding section 'Added', with key NEW = new" - aIni[ "Added" ] := hb_Hash() - aIni[ "Added" ][ "NEW" ] := "new" + hIni[ "Added" ] := hb_Hash() + hIni[ "Added" ][ "NEW" ] := "new" ? "Writing output to parseini_out.ini" - IF hb_IniWrite( "parseini_out.ini", aIni, "#Generated file; don't touch", "#End of file") + IF hb_IniWrite( "parseini_out.ini", hIni, "#Generated file; don't touch", "#End of file") ? "File written" ELSE ? "Can't write file" @@ -59,21 +59,23 @@ PROCEDURE Main( cName ) ? ? "Press any key to next text." Inkey(0) + + nRow := 3 + @nRow, 0 CLEAR ? ? "REPEATING TESTS WITHOUT AUTOMATIC MAIN SECTION" + ? - aIni := hb_IniRead( cName, /*default case*/ , /*Default key indicators */ , .F. ) - - @nRow, 0 + hIni := hb_IniRead( cName, /*default case*/ , /*Default key indicators */ , .F. ) ? "Content of " + cName - IF Empty( aIni ) + IF Empty( hIni ) ? "Not a valid .ini file!" ELSE - FOR EACH cSection IN aIni:Keys + FOR EACH cSection IN hIni:Keys /* Now (without automatic main), toplevel options may be in the root hash */ - aSect := aIni[ cSection ] + aSect := hIni[ cSection ] IF HB_IsHash( aSect ) /* It's a section */ @@ -92,11 +94,11 @@ PROCEDURE Main( cName ) ? ? "Adding section 'Added', with key NEW = new" - aIni[ "Added" ] := hb_Hash() - aIni[ "Added" ][ "NEW" ] := "new" + hIni[ "Added" ] := hb_Hash() + hIni[ "Added" ][ "NEW" ] := "new" ? "Writing output to parseini_out1.ini" - IF hb_IniWrite( "parseini_out1.ini", aIni,; + IF hb_IniWrite( "parseini_out1.ini", hIni,; "#Generated file without main auto section; don't touch", "#End of file",; .F. ) ? "File written" @@ -107,4 +109,71 @@ PROCEDURE Main( cName ) ? "Press any key to next text." Inkey(0) + nRow := 3 + @nRow, 0 CLEAR + ? + ? "WRITING INI TO A STRING" + ? + + cIni := hb_IniWriteStr( hIni ) + + ? "Content of hIni : " + ? + ? cIni + ? + ? "Press any key to next text." + Inkey(0) + + nRow := 3 + @nRow, 0 CLEAR + ? + ? "READING INI FILE FROM A STRING" + ? + + hIni := hb_IniReadStr( cIni, /*default case*/ , /*Default key indicators */ , .F. ) + + ? "Content: " + + IF Empty( hIni ) + ? "Not a valid .ini file!" + ELSE + FOR EACH cSection IN hIni:Keys + /* Now (without automatic main), toplevel options may be in the root hash */ + aSect := hIni[ cSection ] + + IF HB_IsHash( aSect ) + /* It's a section */ + ? + ? "Section [" + cSection + "]" + + FOR EACH cKey IN aSect:Keys + ? cKey + " = " + aSect[ cKey ] + NEXT + ELSE + /* It's a toplevel option */ + ? "TOPLEVEL option:", cSection + " = " + aSect + ENDIF + NEXT + ENDIF + + ? + ? "Press any key to next text." + Inkey(0) + + nRow := 3 + @nRow, 0 CLEAR + ? + ? "WRITING INI FILE TO A STRING " + ? + + cIni := hb_IniWriteStr( hb_IniRead( cName ) ) + + ? "Content of " + cName + ? + ? cIni + ? + ? "Press any key to next text." + Inkey(0) + + RETURN