Enumerate INI
From NSIS Wiki
Jump to navigationJump to search
Author: Zinthose (talk, contrib) |
Summary
Set of macros to enumerate an INI file using syntax similar to the EnumRegKey and EnumRegValue commands.
Example
!include "EnumIni.nsh" Section "Example: EnumIniKey" StrCpy $0 0 loop: ${EnumIniKey} $1 `c:\boot.ini` $0 StrCmp $1 "" done IntOp $0 $0 + 1 ReadIniStr $2 `c:\boot.ini` `boot loader` $1 MessageBox MB_YESNO|MB_ICONQUESTION "Name=$1$\n$\n$\nMore?" IDYES loop done: SectionEnd Section "Example: EnumIniValue" StrCpy $0 0 loop: ${EnumIniValue} $1 `c:\boot.ini` `boot loader` $0 StrCmp $1 "" done IntOp $0 $0 + 1 ReadIniStr $2 `c:\boot.ini` `boot loader` $1 MessageBox MB_YESNO|MB_ICONQUESTION "Name=$1$\nValue=$2$\n$\n$\nMore?" IDYES loop done: SectionEnd
EnumIni.nsh
Latest Stable Release: EnumIni.nsh
/* @FILENAME = EnumIni.nsh @AUTHORS = Zinthose, Iceman_K @REVISIONS = zenpoy[http://forums.winamp.com/member.php?u=401997] @URL = http://nsis.sourceforge.net/mediawiki/index.php?title=Enumerate_INI */ !ifndef __EnumIni__ !define __EnumIni__ ## Includes !include "TextFunc.nsh" !ifndef StrLoc !include "StrFunc.nsh" ${StrLoc} !endif ## Macro to remove leading and trailing whitespaces from a string. ## Derived from the function originaly posted by Iceman_K at: ## http://nsis.sourceforge.net/Remove_leading_and_trailing_whitespaces_from_a_string !ifmacrondef _Trim !macro _Trim _UserVar _OriginalString !define Trim_UID ${__LINE__} Push $R1 Push $R2 Push `${_OriginalString}` Pop $R1 Loop_${Trim_UID}: StrCpy $R2 "$R1" 1 StrCmp "$R2" " " TrimLeft_${Trim_UID} StrCmp "$R2" "$\r" TrimLeft_${Trim_UID} StrCmp "$R2" "$\n" TrimLeft_${Trim_UID} StrCmp "$R2" "$\t" TrimLeft_${Trim_UID} GoTo Loop2_${Trim_UID} TrimLeft_${Trim_UID}: StrCpy $R1 "$R1" "" 1 Goto Loop_${Trim_UID} Loop2_${Trim_UID}: StrCpy $R2 "$R1" 1 -1 StrCmp "$R2" " " TrimRight_${Trim_UID} StrCmp "$R2" "$\r" TrimRight_${Trim_UID} StrCmp "$R2" "$\n" TrimRight_${Trim_UID} StrCmp "$R2" "$\t" TrimRight_${Trim_UID} GoTo Done_${Trim_UID} TrimRight_${Trim_UID}: StrCpy $R1 "$R1" -1 Goto Loop2_${Trim_UID} Done_${Trim_UID}: Pop $R2 Exch $R1 Pop ${_UserVar} !undef Trim_UID !macroend !ifdef Trim !warning `Trim Macro Previously Defined! Beware of bugs!` !else !define Trim `!insertmacro _Trim` !endif !endif ## Global variable needed for indexing the enumerations !ifmacrondef EnumIni_IDX_VAR !macro EnumIni_IDX_VAR !ifndef EnumIni_IDX_VAR VAR /GLOBAL EnumIni_IDX_VAR !define EnumIni_IDX_VAR $EnumIni_IDX_VAR !endif !macroend !endif /* ## EnumIniKey ## Nearly identical in use to the builtin EnumRegKey function, the EnumIniKey macro allows for enumeration of an existing ini file's sections. ## Example ## StrCpy $0 0 loop: ${EnumIniKey} $1 `c:\boot.ini` $0 StrCmp $1 "" done IntOp $0 $0 + 1 MessageBox MB_YESNO|MB_ICONQUESTION "Key=$1$\n$\n$\nMore?" IDYES loop done: */ !ifmacrondef _EnumIniKey !insertmacro EnumIni_IDX_VAR !macro _EnumIniKey _UserVar _IniFilePath _Index !define EnumIniKey_UID ${__LINE__} ClearErrors Push $R0 Push $R1 Push `${_IniFilePath}` Push `${_Index}` Pop $R1 ; ${_Index} Pop $R0 ; ${_IniFilePath} IfFileExists $R0 0 Else_IfFileExists_${EnumIniKey_UID} StrCpy $EnumIni_IDX_VAR -1 ## PATCH Added to Correct 0 length file infinite loop issue discovered by zenpoy ## [http://forums.winamp.com/member.php?u=401997] on January 9th 2012 ${LineSum} $R0 $R1 IfErrors Else_IfFileExists_${EnumINIKey_UID} IntCmp $R1 0 Else_IfFileExists_${EnumINIKey_UID} Else_IfFileExists_${EnumINIKey_UID} 0 ## End Revision ${LineFind} $R0 "/NUL" "1:-1" "EnumIniKey_CALLBACK" IfErrors Else_IfFileExists_${EnumIniKey_UID} Goto EndIf_FileExists_${EnumIniKey_UID} Else_IfFileExists_${EnumIniKey_UID}: StrCpy $R0 '' SetErrors EndIf_FileExists_${EnumIniKey_UID}: Pop $R1 Exch $R0 Pop ${_UserVar} !undef EnumIniKey_UID !macroend !ifndef EnumIniKey !define EnumIniKey `!insertmacro _EnumIniKey` !endif !ifdef __GLOBAL__ !verbose push !verbose 0 Function EnumIniKey_CALLBACK !insertmacro _Trim $R9 $R9 StrCmp $R9 '' End StrCpy $R0 $R9 1 StrCmp $R0 '[' 0 End IntOp $EnumIni_IDX_VAR $EnumIni_IDX_VAR + 1 IntCmp $R1 $EnumIni_IDX_VAR 0 End End ${StrLoc} $R0 $R9 "]" ">" IntCmp $R0 0 End IntOp $R0 $R0 - 1 StrCpy $R0 $R9 $R0 1 Push 'StopLineFind' Return End: StrCpy $R0 '' Push '' FunctionEnd !verbose pop !else !Error `An illegal attempt was made to insert the EnumIniValue_CALLBACK function outside the Global namespace!` !endif !endif /* ## EnumIniValue ## Nearly identical in use to the builtin EnumRegValue function, the EnumIniValue macro allows for enumeration of an existing ini file section. ## Example ## StrCpy $0 0 loop: ${EnumIniValue} $1 `c:\boot.ini` `boot loader` $0 StrCmp $1 "" done IntOp $0 $0 + 1 ReadIniStr $2 `c:\boot.ini` `boot loader` $1 MessageBox MB_YESNO|MB_ICONQUESTION "Value=$1$\n$\t$2$\n$\n$\nMore?" IDYES loop done: */ !ifmacrondef _EnumIniValue !insertmacro EnumIni_IDX_VAR !macro _EnumIniValue _UserVar _IniFilePath _Section _Index !define EnumIniValue_UID ${__LINE__} ClearErrors Push $R0 Push $R1 Push $R2 Push $R3 Push `${_IniFilePath}` Push `${_Section}` Push `${_Index}` Pop $R2 ; ${_Index} Pop $R1 ; ${_Section} Pop $R0 ; ${_IniFilePath} IfFileExists $R0 0 Else_IfFileExists_${EnumIniValue_UID} StrCpy $EnumIni_IDX_VAR -1 ${LineFind} $R0 "/NUL" "1:-1" "EnumIniValue_CALLBACK" IfErrors Else_IfFileExists_${EnumIniValue_UID} Goto EndIf_FileExists_${EnumIniValue_UID} Else_IfFileExists_${EnumIniValue_UID}: StrCpy $R0 '' SetErrors EndIf_FileExists_${EnumIniValue_UID}: Pop $R3 Pop $R2 Pop $R1 Exch $R0 Pop ${_UserVar} !undef EnumIniValue_UID !macroend !ifndef EnumIniValue !define EnumIniValue `!insertmacro _EnumIniValue` !endif !ifdef __GLOBAL__ !verbose push !verbose 0 Function EnumIniValue_CALLBACK !insertmacro _Trim $R9 $R9 StrCmp $R9 '' End StrCpy $R0 $R9 1 StrCmp $R0 ';' End StrCmp $R0 '#' End StrCmp $R0 '[' Key StrCmp $R3 [$R1] 0 End IntOp $EnumIni_IDX_VAR $EnumIni_IDX_VAR + 1 IntCmp $R2 $EnumIni_IDX_VAR 0 End End ${StrLoc} $R0 $R9 "=" ">" IntCmp $R0 0 0 0 ValueSet StrCpy $R0 $R9 ValueSet: StrCpy $R0 $R9 $R0 Push 'StopLineFind' Return Key: StrCpy $R3 $R9 End: StrCpy $R0 '' Push '' FunctionEnd !verbose pop !else !Error `An illegal attempt was made to insert the EnumIniValue_CALLBACK function outside the Global namespace!` !endif !endif !endif
TODO
- OPTIMIZE: Store current INI file line per index to prevent rescanning previously scanned lines.