Skip to content

Instantly share code, notes, and snippets.

@DelPyth
Last active July 10, 2020 08:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DelPyth/cdfd055080f8359746c1ba3d8d6644f5 to your computer and use it in GitHub Desktop.
Save DelPyth/cdfd055080f8359746c1ba3d8d6644f5 to your computer and use it in GitHub Desktop.
Java Properties Styled Data Management
/*
* ========================================================================================================== *
* Author .........: Delta Pythagorean
* Name ...........: Properties.ahk
* Description ....: Java Properties styled parsing and dumping class.
* Date ...........: 2020-07-08 (YYYY-MM-DD)
* Version ........: 1.0.0
* Language .......: English (United States)
* AHK-Version ....: 1.1.32.00
* AHK-Codepage ...: Unicode
* AHK-Bit ........: 64
* ========================================================================================================== *
* Example ........: ; Read a file into an object.
* ................: MyObject := Properties.Parse(A_ScriptDir . "\settings.properties")
* ................: ; Parse an object into a file.
* ................: Properties.Dump(MyObject, A_ScriptDir . "\settings.properties")
* ========================================================================================================== *
*/
Class Properties {
Class Parse Extends Properties.Functor {
Call(FileOrStr) {
ReturnObj := {}
; If the input is a file, then read it.
If (IsObject(FileOrStr) && (FileOrStr.__Handle != Null)) {
FileOrStr := FileOrStr.Read()
} Else {
If (FileExist(FileOrStr)) {
FileRead, FileOrStr, % FileOrStr
}
}
; Combine multiple lines together if they have \ at the end of the line.
FileOrStr := RegExReplace(FileOrStr, "\s\\\R\s*", "\n")
For Index, Line in StrSplit(FileOrStr, "`n", "`r") {
; Trim the line down from any trailing or starting spaces.
Line := Trim(Line)
; Remove comments.
Line := RegExReplace(Line, "im)((?:[\t ]+|)\#.*)$")
If (Line == Null) {
Continue
}
; Determine the keys and values by this: KEY = VALUE
RegExMatch(Line, "Oi)^(?<Key>.+?)\s*=\s*(?<Value>.+)$", Match)
; We save the values to variables instead of using the actual variables because as far as I've tested the match object is read-only.
Key := Match["Key"]
Value := Match["Value"]
; We split the input by a dot because AHK is nice and automatically makes the values into objects if they don't exist already.
Obj := StrSplit(Trim(Key), ".")
; Trim the VALUE from any trailing or leading spaces.
Value := Trim(Value)
; Check if the value is True or False, then set the value like so.
; If it's null. Then set it to be "Null".
; Otherwise modify it to use escapes.
Switch (Value) {
Case "True", "False": {
ReturnObj[Obj*] := %Value% + 0
}
Case "Null": {
; Technically there isn't a Null constant in AHK, but I use use it as a substitute of "" (empty string).
ReturnObj[Obj*] := Null
}
Default: {
Value := StrReplace(Value, "\\", "\")
Value := StrReplace(Value, "\b", "`b")
Value := StrReplace(Value, "\f", "`f")
Value := StrReplace(Value, "\n", "`n")
Value := StrReplace(Value, "\r", "`r")
Value := StrReplace(Value, "\t", "`t")
; Thanks to Lexikos from: https://autohotkey.com/board/topic/63263-unicode-escaped-string-convert-u00/
If (Value ~= "\\u[A-Fa-f0-9]{1,4}") {
i := 1
While (j := RegExMatch(Value, "\\u[A-Fa-f0-9]{1,4}", m, i)) {
e .= SubStr(Value, i, j - i) . Chr("0x" SubStr(m, 3))
i := j + StrLen(m)
}
Value := e . SubStr(Value, i)
}
ReturnObj[Obj*] := Value
}
}
}
Return (ReturnObj)
}
}
Class Dump Extends Properties.Functor {
Call(Object, File := False, LineEnd := "`r`n", __PathTo := False) {
ReturnStr := Null
If (!IsObject(Object)) {
Throw Exception("Parameter must be an object", -2, Object)
Return (False)
}
For Key, Value in Object {
If (IsObject(Value)) {
ReturnStr .= Properties.Dump(Value, False, LineEnd, (((__PathTo != False) ? (__PathTo . ".") : (Null)) . Key))
} Else {
Value := StrReplace(Value, "\", "\\")
Value := StrReplace(Value, "`b", "\b")
Value := StrReplace(Value, "`f", "\f")
Value := StrReplace(Value, "`n", "\n")
Value := StrReplace(Value, "`r", "\r")
Value := StrReplace(Value, "`t", "\t")
ReturnStr .= ((__PathTo != False) ? (__PathTo . ".") : (Null)) . (Key . " = " . Value . LineEnd)
}
}
If (File == False) {
Return (ReturnStr)
} Else {
If ((IsObject(File)) && (File.__Handle != Null)) {
File.Write(ReturnStr)
} Else {
FileAppend, % ReturnStr, % File
}
Return ((ErrorLevel == True) ? (True) : (ReturnStr))
}
}
}
Class Functor {
__Call(Method, Args*) {
Return (New This).Call(Args*)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment