#include-once ; #INDEX# ======================================================================================================================= ; Title .........: IniEx (1.0) ; Date ..........: 06.02.2011 ; AutoIt Version : 3.3 + (development version = 3.3.6.0) ; Language ......: English ; Description ...: Extra functions for an extended ini support: ;  - Functions to change the ini's encoding format and allow to use ;    unicode for all ini-functions, prefered UTF-16 Little Endian since it's the fastest in AutoIt ;  - Functions to read and write a whole ini into or from one three-dimensional array; also from a string ;  - Functions to read keys, sections and sectionnames from a string instead of a file ; Remarks .......: ; Link ..........: http://www.autoitscript.com/forum/topic/125163-iniex-udf/ ; Author ........: FichteFoll ; =============================================================================================================================== ; #CHANGELOG# =================================================================================================================== ; ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; _IniConvertToUnicode  Converts encoding format of a text file to UTF-16 Little Endian ; _IniConvertToANSI Converts encoding format of a text file to ANSI ; _IniReadToArray   Returns the whole ini file into one array with three dimensions ; _IniWriteFromArray    Writes or creates an Ini out of an array ; _IniReadFromString    Returns the value of a key in a specific section of an ini-formatted string ; _IniReadSectionNamesFromString    Returns all keys and its values from a given section name of an ini-formatted string ; _IniReadSectionFromString Returns all section names of an ini-formatted string ; _IniReadToArrayFromString Returns the whole ini file into one array with three dimensions ; =============================================================================================================================== ; #INTERNAL_USE_ONLY# =========================================================================================================== ; __StringEscapeRegExp ; =============================================================================================================================== ; ############################################################################################################################### ; ############################################################################################################################### ;#Function# ===================================================================================================================== ; Name............: _IniConvertToUnicode ; Description.....: Converts encoding format of a text file to UTF-16 Little Endian ; Syntax..........: _IniConvertToUnicode($szFile, $fCreate = True) ; Parameters......: ;   $szFile  - Path to text file (won't work with binary encoded files) ;   $fCreate - [optional]  The File will be created if it does not exist (default) ; Return values ..: ;   Success  - Returns 1 - sets @extended = 1 if the file is already encoded correctly ;   Failure  - Returns 0 - sets @error ;  | 1 - The file does not exist (requires $fCreate = False) ;  | 2 - The file is not a text file ;  | 3 - Reading the file failed ;  | 4 - Opening the file with unicode failed ;  | 5 - Writing the file with unicode failed ; Author .........: FichteFoll ; Remarks ........: Use the related functions and _IniReadToArray or _IniWriteFromArray to access a unicode-formatted ini. ;   If the file does not exist it will be created. ; Related ........: FileGetEncoding, IniRead, IniWrite, IniReadSection, IniWriteSection, IniReadSectionNames ; Link ...........; See on top ; Example ........; _IniConvertToUnicode("c:/file.ini") ; =============================================================================================================================== Func _IniConvertToUnicode($szFile, $fCreate = True) If Not FileExists($szFile) And $fCreate = False Then Return SetError(1) Local $iEncoding, $szContent, $f $iEncoding = FileGetEncoding($szFile) Switch $iEncoding Case 32 Return SetExtended(1, 1) ; Nothing to be done Case -1 If FileExists($szFile) Then SetError(2) ContinueCase Case Else $szContent = FileRead($szFile) If @error And FileExists($szFile) Then Return SetError(3) $f = FileOpen($szFile, 2 + 8 + 32) ; delete, create, utf-16 le If $f = -1 Then Return SetError(4) If FileWrite($f, $szContent) = 0 Then SetError(5, FileClose($f) * 0) FileClose($f) Return 1 EndSwitch EndFunc;==>_IniConvertToUnicode ;#Function# ===================================================================================================================== ; Name............: _IniConvertToANSI ; Description.....: Converts encoding format of a text file to ANSI ; Syntax..........: _IniConvertToANSI($szFile, $fCreate = True) ; Parameters......: ;   $szFile  - Path to text file (won't work with binary encoded files) ;   $fCreate - [optional]  The File will be created if it does not exist (default) ; Return values ..: ;   Success  - Returns 1 - sets @extended = 1 if the file is already encoded correctly ;   Failure  - Returns 0 - sets @error ;  | 1 - The file does not exist (requires $fCreate = False) ;  | 2 - The file is not a text file ;  | 3 - Reading the file failed ;  | 4 - Opening the file with ANSI failed ;  | 5 - Writing the file with ANSI failed ; Author .........: FichteFoll ; Modified........: ; Remarks ........: This is the oppsite of _IniConvertToUnicode. Characters that are Uincode-only will be converted to '?'. ; Related ........: FileGetEncoding, IniRead, IniWrite, IniReadSection, IniWriteSection, IniReadSectionNames ; Link ...........; See on top ; Example ........; _IniConvertToANSI("c:/file.ini") ; =============================================================================================================================== Func _IniConvertToANSI($szFile, $fCreate = True) If Not FileExists($szFile) And $fCreate = False Then Return SetError(1) Local $iEncoding, $szContent, $f $iEncoding = FileGetEncoding($szFile) Switch $iEncoding Case 0 Return SetExtended(1, 1) ; Nothing to be done Case -1 If FileExists($szFile) Then SetError(2) ContinueCase Case Else $szContent = FileRead($szFile) If @error And FileExists($szFile) Then Return SetError(3) $f = FileOpen($szFile, 2 + 8 + 0) ; delete, create, ansi If $f = -1 Then Return SetError(4) If FileWrite($f, $szContent) = 0 Then SetError(5) FileClose($f) Return 1 EndSwitch EndFunc;==>_IniConvertToANSI ; ############################################################################################################################### ;#Function# ============================================================================================================================================ ; Name............: _IniReadToArray ; Description.....: Returns the whole ini file into one array with three dimensions ; Syntax..........: _IniReadToArray($szFile) ; Parameters......: ;   $szFile  - Path to the ini file ; Return values ..: ;   Success  - Returns an array containing all sections, keys and values (see Remarks) ;   Failure  - Returns 0 and sets @error = 1 if the section names could not be determined ; Author .........: FichteFoll ; Modified........: ; Remarks ........: On success the array has the following structure: ;  [0][0][0] = section count ;  [n][0][0] = nth Section name ;  [n][0][1] = nth Section's key count ;  [n][m][0] = nth Section's mth key's name (just like IniReadSection) ;  [n][m][1] = nth Section's mth key's value (just like IniReadSection) ;   If some sections could not be allocated, its key count is set to 0 which also happens if there is no key in the section. ;   Check @extended for the total count of sections that could not be read or have 0 keys inside. ; Related ........: _IniWriteFromArray, IniReadSectionNames, IniReadSection ; Link ...........; See on top ; Example ........; $aArray = _IniReadToArray("c:\file.ini") ;   For $i = 1 To $aArray[0][0][0] ;   ConsoleWrite(StringFormat("! [%s]", $aArray[$i][0][0]) & @CRLF) ;   For $j = 1 To $aArray[$i][0][1] ;   ConsoleWrite(StringFormat("- %s=%s", $aArray[$i][$j][0], $aArray[$i][$j][1]) & @CRLF) ;   Next ;   Next ; ====================================================================================================================================================== Func _IniReadToArray($szFile) Local $aszSections, $aReturn[1], $aszSection, $iMaxKeys = 1, $ext $aszSections = IniReadSectionNames($szFile) If @error Then Return SetError(1) ReDim $aReturn[$aszSections[0] + 1][$iMaxKeys + 1][2] $aReturn[0][0][0] = $aszSections[0] For $i = 1 To $aszSections[0] $aReturn[$i][0][0] = $aszSections[$i] $aszSection = IniReadSection($szFile, $aszSections[$i]) If @error Then ; ususally no errors here, just go to next section in that case $aReturn[$i][0][1] = 0 $ext += 1 ContinueLoop EndIf $aReturn[$i][0][1] = $aszSection[0][0] If $aszSection[0][0] > $iMaxKeys Then $iMaxKeys = $aszSection[0][0] ReDim $aReturn[$aszSections[0] + 1][$iMaxKeys + 1][2] EndIf For $j = 1 To $aszSection[0][0] $aReturn[$i][$j][0] = $aszSection[$j][0] $aReturn[$i][$j][1] = $aszSection[$j][1] Next Next Return SetExtended($ext, $aReturn) EndFunc;==>_IniReadToArray ;#Function# ===================================================================================================================== ; Name............: _IniWriteFromArray ; Description.....: Writes or creates an Ini out of an array ; Syntax..........: _IniWriteFromArray($szFile, Const ByRef $aArray, $fUnicode = False, $fDelete = True) ; Parameters......: ;   $szFile  - Path to the ini file ;   Const ByRef $aArray  - The array containing the ini data; with three dimensions, 2 elements in the third and the following format: ;   [0][0][0|1] - not relevant, can contain values from _IniReadToArray ;  ![n][0][0] - nth section name ;   [n][0][1] - not relevant, can contain value from _IniReadToArray ;  ![n][m][0] - nth section's mth key name ;  ![n][m][1] - nth section's mth key value ;   $fUnicode    - [optional] The ini will be encoded with Unicode using _IniConvertToUnicode ;   $fDelete - [optional] The whole file gets deleted before the array will be written into it; ; sections will always be overwritten ; Return values ..: ;   Success  - Returns 1 ;   Failure  - Returns 0 - sets @error ;  | 1 - Array is badly formatted ;  | 2 - Ini could not be converted to Unicode ;  | 3 - Every section has failed to be written ; Author .........: FichteFoll ; Remarks ........: This function is the opposite of _IniReadToArray and compatible with its return value. ;   If a section fails to be written @extended is set to the total count of failures. ;   If @extended is going to be the total count of sections @error is set to 3 and 0 returned. ; Related ........: _IniReadFromArray, IniWriteSection ; Link ...........; See on top ; Example ........; $aArray = _IniReadToArray("c:\file.ini") ;   $aArray[1][1][1] = "the first value of this ini has changed" ;   _IniWriteFromArray("c:\file2.ini", $aArray, True) ; =============================================================================================================================== Func _IniWriteFromArray($szFile, Const ByRef $aArray, $fUnicode = False, $fDelete = True) If UBound($aArray, 0) <> 3 Or UBound($aArray, 3) <> 2 Then Return SetError(1) ; bad formatted If $fDelete Then FileDelete($szFile) If $fUnicode Then _IniConvertToUnicode($szFile) If @error Then Return SetError(2) EndIf Local $ext = 0 For $i = 1 To UBound($aArray, 1) - 1 Local $aszSection[1][2] For $j = 1 To UBound($aArray, 2) - 1 If $aArray[$i][$j][0] = "" And $aArray[$i][$j][1] = "" Then ExitLoop ; empty entry ReDim $aszSection[$j+1][2] $aszSection[$j][0] = $aArray[$i][$j][0] $aszSection[$j][1] = $aArray[$i][$j][1] Next IniWriteSection($szFile, $aArray[$i][0][0], $aszSection) If @error Then $ext += 1 Next If $ext = UBound($aArray, 1) Then Return SetError(3) Return SetExtended($ext, 1) EndFunc;==>_IniWriteFromArray ; ############################################################################################################################### ;#Function# ===================================================================================================================== ; Name............: _IniReadFromString ; Description.....: Returns the value of a key in a specific section of an ini-formatted string ; Syntax..........: _IniReadFromString($szInput, $szSection, $szKey, $Default) ; Parameters......: ;   $szInput - The string that contains data in ini format ;   $szSection   - The sectionname (just as in IniRead) ;   $szKey   - The keyname (just as in IniRead) ;   $Default - The default value if the key does not exist or reading failed (just as in IniRead) ; Return values ..: ;   Success  - Returns the read value ;   Failure  - Returns $Default ; Author .........: FichteFoll ; Remarks ........: Works for Unicode as well as for ANSI ; Related ........: IniRead, _IniReadSectionFromString ; Link ...........; See on top ; Example ........; $var = _IniReadFromString(StringFormat("[Sect]\r\nMyKey1=value1\r\nMyKey2=value2"), "Sect", "MyKey2", "no_value") ; =============================================================================================================================== Func _IniReadFromString($szInput, $szSection, $szKey, $Default) $szInput = StringStripCR($szInput) ;~  Local $aRegMl = StringRegExp($szInput, "\[" & __StringEscapeRegExp($szSection) & "\]\n+(?:[^\[].*?=.*\n)*" & __StringEscapeRegExp($szKey) & "=(.*)\n?(",3) Local $aRegMl = StringRegExp($szInput, "\[" & __StringEscapeRegExp($szSection) & "\]\n+(?:[^\[].*?=.*\n)*" & __StringEscapeRegExp($szKey) & "=(.*)\n?", 3) If @error Then Return SetError(1, 0, $Default) ; key not found    Return $aRegMl[0] EndFunc;==>_IniReadFromString ;#Function# ===================================================================================================================== ; Name............: _IniReadSectionNamesFromString ; Description.....: Returns all section names of an ini-formatted string ; Syntax..........: _IniReadSectionNamesFromString($szInput) ; Parameters......: ;   $szInput - The string that contains data in ini format ; Return values ..: ;   Success  - Returns an array containing the section names; $result[0] contains the number of sections ;   Failure  - Returns 0 and sets @error = 1 which means that no sections were found, this can have several reasons ; Author .........: FichteFoll ; Remarks ........: A section does not have to contain keys ; Related ........: IniReadSectionNames, IniReadSection ; Link ...........; See on top ; Example ........; $result = _IniReadSectionNamesFromString(StringFormat("[Sect]\r\nMyKey1=value1\r\nMyKey2=value2"), "Sect", "MyKey2", "no_value") ; =============================================================================================================================== Func _IniReadSectionNamesFromString($szInput) $szInput = StringStripCR($szInput) Local $aRegMl = StringRegExp($szInput, "(?<=\n|\A)\[(.*)\](?!.|\Z)", 3) If @error Then Return SetError(1) ; nothing found Local $iUBound = UBound($aRegMl), $aReturn[$iUBound + 1] $aReturn[0] = $iUBound For $i = 0 To $iUBound - 1 $aReturn[$i + 1] = $aRegMl[$i] Next Return $aReturn EndFunc;==>_IniReadSectionNamesFromString ;#Function# ===================================================================================================================== ; Name............: _IniReadSectionFromString ; Description.....: Returns all keys and its values from a given section name of an ini-formatted string ; Syntax..........: _IniReadSectionFromString($szInput, $szSection) ; Parameters......: ;   $szInput - The string that contains data in ini format ;   $szSection   - The section name ; Return values ..: ;   Success  - Returns an array containing the data; ;  $result[0][0] will contain the number of sectins, [n][0] the key and [n][1] the value ;   Failure  - Returns 0 and sets @error = 1 meaning that the section was not found ; Author .........: FichteFoll ; Remarks ........: [0][0] can be 0 if the section has no keys, the array will not have any more elements ; Related ........: IniReadSection, IniWriteSection ; Link ...........; See on top ; Example ........; $result = _IniReadSectionFromString(StringFormat("[Sect]\r\nMyKey1=value1\r\nMyKey2=value2"), "Sect") ; =============================================================================================================================== Func _IniReadSectionFromString($szInput, $szSection) ; Using RegExp rarely does not work; using workaround by parsing the lines into an array instead ;~  $szInput = StringStripCR(StringRegExpReplace($szInput, "\r(?!\n)", "\r\n")) ;~  Local $aRegMl = StringRegExp($szInput, "(?<=\n|\A)\[" & __StringEscapeRegExp($szSection) & "\](?:\n+?(.*?)=(.*))+(?=\n?\Z|\n\[)", 1) ;~  ;Local $aRegMl = StringRegExp($szInput, "(?:\n+?(.*?)=(.*))+", 3) ;~  ;Local $aRegMl = StringRegExp($szInput, "(?:\n(.*?)=(.*))", 3) ;~  If @error Then Return SetError(1) ; section not found ;~  ;_ArrayDisplay($aRegMl) ;~  Local $iUBound = UBound($aRegMl), $aReturn[$iUBound / 2 + 1][2] ;~  $aReturn[0][0] = $iUBound / 2 ;~  For $i = 0 To $iUBound - 1 ;~  Switch Mod($i, 2) ;~  Case 0 ;~  $aReturn[Floor(($i) / 2) + 1][0] = $aRegMl[$i] ;~  Case 1 ;~  $aReturn[Floor(($i) / 2) + 1][1] = $aRegMl[$i] ;~  EndSwitch ;~  Next ;~  Return $aReturn $szInput = StringStripCR(StringRegExpReplace($szInput, "\r(?!\n)", "\r\n")) Local $aszLines = StringSplit($szInput, @LF), $aReturn[1][2] = [[0, 0]], $fFound = False, $aRegMl, $j = 0 For $i = 1 To $aszLines[0] If $aszLines[$i] = StringFormat("[%s]", $szSection) Then $fFound = True ContinueLoop EndIf If $fFound Then $aRegMl = StringRegExp($aszLines[$i], "(.*?)=(.*)", 1) If @error Then ExitLoop $j += 1 $aReturn[0][0] = $j ReDim $aReturn[$aReturn[0][0] + 1][2] $aReturn[$j][0] = $aRegMl[0] $aReturn[$j][1] = $aRegMl[1] EndIf Next If $fFound = False Then Return SetError(1) ;If $j = 0 Then Return SetError(2) ; return empty array instead Return $aReturn EndFunc;==>_IniReadSectionFromString ;#Function# ============================================================================================================================================ ; Name............: _IniReadToArrayFromString ; Description.....: Returns the whole ini file into one array with three dimensions ; Syntax..........: _IniReadToArrayFromString($szFile) ; Parameters......: ;   $szInput  - The string that contains data in ini format ; Return values ..: ;   Success  - Returns an array containing all sections, keys and values (see Remarks) ;   Failure  - Returns 0 and sets @error = 1 if the section names could not be determined ; Author .........: FichteFoll ; Modified........: ; Remarks ........: On success the array has the following structure: ;  [0][0][0] = section count ;  [n][0][0] = nth Section name ;  [n][0][1] = nth Section's key count ;  [n][m][0] = nth Section's mth key's name (just like IniReadSection) ;  [n][m][1] = nth Section's mth key's value (just like IniReadSection) ;   If some sections could not be allocated, its key count is set to 0 which also happens if there is no key in the section. ;   Check @extended for the total count of sections that could not be read or have 0 keys inside. ; Related ........: _IniReadToArray, _IniWriteToArray, _IniReadSectionNamesFromString, _IniReadSectionFromString ; Link ...........; See on top ; Example ........; $aArray = _IniReadToArrayFromString(StringFormat("[Sect]\r\nMyKey1=value1\r\nMyKey2=value2\r\n[Sect_2]\r\nYourKey1=value1")) ;   For $i = 1 To $aArray[0][0][0] ;   ConsoleWrite(StringFormat("! [%s]", $aArray[$i][0][0]) & @CRLF) ;   For $j = 1 To $aArray[$i][0][1] ;   ConsoleWrite(StringFormat("- %s=%s", $aArray[$i][$j][0], $aArray[$i][$j][1]) & @CRLF) ;   Next ;   Next ; ====================================================================================================================================================== Func _IniReadToArrayFromString($szInput) Local $aszSections, $aReturn[1], $aszSection, $iMaxKeys = 1, $ext $aszSections = _IniReadSectionNamesFromString($szInput) If @error Then Return SetError(1) ReDim $aReturn[$aszSections[0] + 1][$iMaxKeys + 1][2] $aReturn[0][0][0] = $aszSections[0] For $i = 1 To $aszSections[0] $aReturn[$i][0][0] = $aszSections[$i] $aszSection = _IniReadSectionFromString($szInput, $aszSections[$i]) If @error Then ; ususally no errors here, just go to next section in that case $aReturn[$i][0][1] = 0 $ext += 1 ContinueLoop EndIf $aReturn[$i][0][1] = $aszSection[0][0] If $aszSection[0][0] > $iMaxKeys Then $iMaxKeys = $aszSection[0][0] ReDim $aReturn[$aszSections[0] + 1][$iMaxKeys + 1][2] EndIf For $j = 1 To $aszSection[0][0] $aReturn[$i][$j][0] = $aszSection[$j][0] $aReturn[$i][$j][1] = $aszSection[$j][1] Next Next Return SetExtended($ext, $aReturn) EndFunc;==>_IniReadToArrayFromString ; ############################################################################################################################### ; =============================================== ; = Internal Use Only ; =============================================== Func __StringEscapeRegExp($szExp) Return StringRegExpReplace($szExp, "([\(\)\[\]\{\}\\\/\?\.\\|\+])", "\\$1") ; ()[]{}\/?.|+ EndFunc;==>__StringEscapeRegExp