-
Notifications
You must be signed in to change notification settings - Fork 3
/
ini.bmx
335 lines (241 loc) · 7.32 KB
/
ini.bmx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
' Code for handling INI files, taken from BlitzBasic forums, by Perturbatio
' http://www.blitzmax.com/codearcs/codearcs.php?code=1890
' Modified by Chris Eykamp to make it more flexible
' Code in this section is public domain
' CE Apr-2007 Better support for comments and whitespace in INI file
' CE 26-Apr-2007 Fixed problem with empty values (lines that look like key =)
SuperStrict
Import brl.filesystem
Import brl.linkedlist
Import brl.map
Function Trim:String(xs:String)
Return xs.Trim()
End Function
Function SplitString:TList(inString:String, Delim:String)
Local tempList : TList = New TList
Local currentChar : String = ""
Local count : Int = 0
Local TokenStart : Int = 0
If Len(Delim)<1 Then Return Null
inString = Trim(inString)
For count = 0 Until Len(inString)
If inString[count..count+1] = delim Then
tempList.AddLast(inString[TokenStart..Count])
TokenStart = count + 1
End If
Next
tempList.AddLast(inString[TokenStart..Count])
Return tempList
End Function
Type TIniSection
Field Name:String
Field Values:TMap
Method SetValue(key:String, value:Object)
Values.Insert(Key, Value)
End Method
Method GetValue:String(Key:String)
Return String(Values.ValueForKey(Key))
End Method
Method DeleteValue(Key:String)
Values.Remove(Key)
End Method
Method GetSectionText:String()
Local result:String = "["+Name+"]~r~n"
For Local s:Object = EachIn Values.keys()
result = result + String(s) + "=" + String(Values.ValueForKey(s)) + "~r~n"
Next
Return result+"~r~n"
End Method
Function Create:TIniSection(name:String)
Local tempSection:TIniSection = New TIniSection
tempSection.name = name
tempSection.Values = New TMap
Return tempSection
End Function
End Type
Type TSectionList
Field _Sections:TIniSection[]
Method GetSection:TIniSection(sectionName:String)
For Local section:TIniSection = EachIn _Sections
If section.Name = sectionName Then Return section
Next
Return Null
End Method
Method AddSection:TIniSection(sectionName:String)
Local currentLength:Int = Len(_Sections)
_Sections = _Sections[..currentLength+1]
_Sections[currentLength] = TIniSection.Create(sectionName)
Return _Sections[currentLength]
End Method
Method RemoveSection:Int(sectionName:String)
Local currentLength:Int = Len(_Sections)
For Local i:Int = 0 To currentLength-1
If _Sections[i].Name = sectionName Then
If i < currentLength-1 Then
For Local x:Int = i To currentLength-2
_Sections[x] = _Sections[x+1]
Next
EndIf
_Sections = _Sections[..currentLength-1]
Return True
EndIf
Next
Return False
End Method
Function Create:TSectionList()
Local tempSectionList:TSectionList = New TSectionList
Return tempSectionList
End Function
End Type
Type TPertIni
Field Filename:String
Field Loaded:Int
Field Saved:Int
Field Sections:TSectionList
Method Load:Int()
Local file:TStream
Local line:String
Local tempList:TList
Local tempArray:Object[]
Local currentSection:String = ""
Local error:String
Local v:String
If FileType(Filename) = 1 Then
file:TStream = ReadStream(FileName)
While Not Eof(file)
line = cleanVal(ReadLine(file))
If Not (Line[..1] = ";") Then ' Skip lines that are just comments
If Line[..1] = "[" And Line[Len(Line)-1..] = "]" Then
currentSection = Line[1..Len(Line)-1]
AddSection(currentSection)
Else
If Len(currentSection) > 0 And Len(line) > 0 Then
tempArray = smartSplit(Line, "=")
If tempArray <> Null
If tempArray.length > 1 Then
v = String(tempArray[1]).Trim()
Else
v = ""
EndIf
SetSectionValue(currentSection, String(tempArray[0]).Trim(), v)
EndIf
Else If Len(Line) > 0 Then
Return False 'no section header found'
EndIf
EndIf
EndIf
Wend
CloseStream(file)
EndIf
Return False
End Method
Method Save:Int(Overwrite:Int = False)
Local file:TStream
Local ft:Int = FileType(Filename)
If ft = 0 Or (ft = 1 And Overwrite = True) Then
file:TStream = WriteStream(FileName)
WriteString(file, GetIniText())
CloseStream(file)
Else
Return False
EndIf
End Method
Method AddSection:TIniSection(sectionName:String)
Return Sections.AddSection(sectionName)
End Method
Method GetSection:TIniSection(sectionName:String)
Return Sections.GetSection(sectionName)
End Method
Method SetSectionValue(sectionName:String, key:String, value:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].SetValue(key, value)
Return
EndIf
Next
End Method
Method DeleteSectionValue(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Sections._Sections[i].DeleteValue(key)
Return
EndIf
Next
End Method
Method GetSectionValue:String(sectionName:String, key:String)
For Local i:Int = 0 To Len(Sections._Sections) -1
If Sections._Sections[i].name = sectionName Then
Return Sections._Sections[i].GetValue(key)
EndIf
Next
End Method
Method GetIniText:String()
Local result:String
For Local section:TIniSection = EachIn Sections._Sections
result:+section.GetSectionText()
Next
Return result
End Method
Function Create:TPertIni(filename:String)
Local tempIni:TPertIni = New TPertIni
tempIni.Filename = filename
tempIni.Sections:TSectionList = TSectionList.Create()
Return tempIni
End Function
End Type
'###############################################################################
' Trim any whitespace or comments from value
Function cleanVal:String(s:String)
If s Then Return smartSplit(s.Trim(),";")[0] Else Return Null
End Function
'###############################################################################
' Split a string into substrings
' From http://www.blitzbasic.com/codearcs/codearcs.php?code=1560
' by CoderLaureate, bug fix by Chris Eykamp
' This code has been declared by its author to be Public Domain code.
Function SmartSplit:String[](str:String, dels:String, text_qual:String = "~q")
Local Parms:String[] = New String[1]
Local pPtr:Int = 0
Local chPtr:Int = 0
Local delPtr:Int = 0
Local qt:Int = False
Local str2:String = ""
Repeat
Local del:String = Chr(dels[delPtr])
Local ch:String = Chr(str[chPtr])
If ch = text_qual Then
If qt = False Then
qt = True
Else
qt = False
End If
End If
If ch = del Then
If qt = True Then str2:+ ch
Else
str2:+ ch
End If
If ch = del Or chPtr = str.Length - 1 Then
If qt = False Then
Parms[pPtr] = str2.Trim()
str2 = ""
pPtr:+ 1
Parms = Parms[..pPtr + 1]
If dels.length > 1 And delPtr < dels.length Then delPtr:+ 1
End If
End If
chPtr:+ 1
If chPtr >= str.Length Then Exit
Forever
If Parms.Length > 1 Then Parms = Parms[..Parms.Length - 1]
Return Parms
End Function
Function IniLoadDef:String(ini:TPertIni, section:String, Key:String, def:String)
If ini.GetSection(section) = Null
ini.AddSection(section)
ini.SetSectionValue(section, key, def)
ElseIf ini.GetSectionValue(section, key) = Null
ini.SetSectionValue(section, key, def)
EndIf
Return ini.GetSectionValue(section, key)
End Function