Ini file library
Monkey Forums/Monkey Beginners/Ini file library
| ||
| Hi ! I'm searching a way to parse an short ini file. (i only want read values) So is there already a monkey code example to do this ? Many Thanks. |
| ||
Hi, I have written a module for this.
'--------------------------------------------------------------------------
' File Format: Custom ini file
'
' [ Section ]
' value = property
' multilineValue = {--
' 0 1 2 3 4 5 6 7 8
' 9 10 11 12 13 14 15
' 16 17 18 19 20 21
' --}
'--------------------------------------------------------------------------
Strict
Import mojo.app
Class IniFile
Method New(path:String)
Local text:= LoadString(path)
If text
InitWithString(text, path)
End
End
Method InitWithString:Void(iniString:String, name:String = "unnamed")
Local lines:String[] = iniString.Split("~n")
Local currentSection:IniSection
Local multilineMode:Bool = False
Local multilineData:String
Local multilineProp:String
sections = New StringMap<IniSection>
AddSection(GLOBALS)
currentSection = GetGlobals()
For Local i:Int = 0 Until lines.Length
Local line:String = lines[i].Trim()
'comments
If line.Length = 0 Or line.StartsWith("#")
'Do nothing
'read multiple lines
ElseIf multilineMode
If line = MULTILINE_END
multilineMode = False
SetProperty(currentSection, multilineProp, multilineData)
Else
multilineData += line + " "
End
'sections
ElseIf line.StartsWith("[")
If line.EndsWith("]")
Local sectionID:String = line[1..-1].Trim()
If sections.Contains(sectionID)
GenerateError("Section " + sectionID + " has already been declared! (on line " + (i+1) + ")", name)
Else
AddSection(sectionID)
currentSection = GetSection(sectionID)
End
Else
GenerateError("Sections must be closed! (on line " + (i+1) + ")", name)
End
'properties
Else
Local delimiterIndex:Int = line.Find(DELIMITER)
If delimiterIndex = -1
GenerateError("Attempting to parse line " + (i+1) + ": " + line + "~nbut could not find the delimiter " + DELIMITER, name)
End
Local leftSide:String = line[0..delimiterIndex].Trim()
Local rightSide:String = line[delimiterIndex+1..].Trim()
If rightSide = MULTILINE_START
multilineMode = True
multilineProp = leftSide
Else
SetProperty(currentSection, leftSide, rightSide)
End
End
Next
If multilineMode
GenerateError("You forgot to close a multiline property with ~q" + MULTILINE_START + "~q", name)
End
End
Method Get:String(value:String, fallback:String = "")
Local g:= GetGlobals()
If g
Return g.GetString(value, fallback)
End
Return fallback
End
Method GetSection:IniSection(section:String)
Return sections.Get(section)
End
Method GetGlobals:IniSection()
Return GetSection(GLOBALS)
End
Method AddSection:Void(id:String)
Local s:= New IniSection
s.id = id
s.data = New StringMap<String>
sections.Add(id, s)
End
Method SetProperty:Void(section:IniSection, prop:String, value:String)
If Not section Then Return
If section.data.Contains(prop)
section.data.Set(prop, value)
Else
section.data.Add(prop, value)
End
End
Private
Field sections:StringMap<IniSection> = New StringMap<IniSection>
Const DELIMITER:String = "="
Const GLOBALS:String = "_GLOBALS_"
Const MULTILINE_START:String = "{--"
Const MULTILINE_END:String = "--}"
Method GenerateError:Void(message:String, name:String)
Error("IniFile " + name + "~n" + message)
sections = Null
End
'could be used for quote parsing
Method ParseString:String(rawString:String)
Local trimmed:String = rawString.Trim()
Local findQuote:Int = trimmed.Find("~q")
If findQuote = -1 Then Return trimmed
If trimmed[0] = "~q"[0] And trimmed[trimmed.Length-1] = "~q"[0]
Return trimmed[1..trimmed.Length-1]
End
Return ""
End
End
Class IniSection
Method ID:String() Property
Return id
End
Method GetString:String(prop:String, fallback:String = "")
Local value:= data.Get(prop)
If Not value
Return fallback
End
Return value
End
Method GetInt:Int(prop:String, fallback:Int = 0)
If Not data.Contains(prop)
Return fallback
End
Return Int(data.Get(prop))
End
Method GetFloat:Float(prop:String, fallback:Float = 0.0)
If Not data.Contains(prop)
Return fallback
End
Return Float(data.Get(prop))
End
Method GetBool:Bool(prop:String, fallback:Bool = False)
If Not data.Contains(prop)
Return fallback
End
Local result:String = data.Get(prop)
result = result.ToLower()
Select result
Case "0", "no", "false", "off"
Return False
Case "1", "yes", "true", "on"
Return True
End
Return fallback
End
Private
Field data:StringMap<String>
Field id:String
End
Usage is like this
Local ini:= New IniFile("path.ini")
Local globals:= ini.GetGlobals()
Print globals.GetInt("width") 'prints 100
Print globals.GetString("description") 'prints Hello World
Local colors:= ini.GetSection("ColorSection")
Print colors.GetFloat("red") 'prints 1.0
Print colors.GetFloat("green") 'prints 0.5
Print colors.GetFloat("blue") 'prints 0.2
Print colors.GetFloat("yellow", 0.8) 'prints 0.8 (fallback) because yelllow was not found
assuming an ini file like this # This is a comment, values below are in the global section width = 100 description = Hello World [ ColorSection ] red = 1.0 green = 0.5 blue = 0.2 ----- edit: added convinience method Get() which will use the global section automatically.
Local ini:= New IniFile("path.ini")
Print ini.Get("width") 'prints 100
|
| ||
| Many thanks to share this Shinkiro1 |