Skip to content

Commit ebf5ece

Browse files
committed
Added documentation
1 parent ff82bfb commit ebf5ece

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

properties.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,39 @@
2727
* the GNU General Public License.
2828
*/
2929

30+
/*
31+
Package properties is a library for handling maps of hierarchical properties.
32+
This library is mainly used in the Arduino platform software to handle
33+
configurations made of key/value pairs stored in files with an INI like
34+
syntax, for example:
35+
36+
...
37+
uno.name=Arduino/Genuino Uno
38+
uno.upload.tool=avrdude
39+
uno.upload.protocol=arduino
40+
uno.upload.maximum_size=32256
41+
uno.upload.maximum_data_size=2048
42+
uno.upload.speed=115200
43+
uno.build.mcu=atmega328p
44+
uno.build.f_cpu=16000000L
45+
uno.build.board=AVR_UNO
46+
uno.build.core=arduino
47+
uno.build.variant=standard
48+
diecimila.name=Arduino Duemilanove or Diecimila
49+
diecimila.upload.tool=avrdude
50+
diecimila.upload.protocol=arduino
51+
diecimila.build.f_cpu=16000000L
52+
diecimila.build.board=AVR_DUEMILANOVE
53+
diecimila.build.core=arduino
54+
diecimila.build.variant=standard
55+
...
56+
57+
This library has methods to parse this kind of files into a Map object.
58+
59+
The Map object has many helper methods to accomplish some common operation
60+
on this kind of data like cloning, merging, comparing and also extracting
61+
a submap or generating a map-of-submaps from the first "level" of the hierarchy.
62+
*/
3063
package properties
3164

3265
import (
@@ -55,6 +88,7 @@ func init() {
5588
}
5689
}
5790

91+
// Load reads a properties file and makes a Map out of it.
5892
func Load(filepath string) (Map, error) {
5993
bytes, err := ioutil.ReadFile(filepath)
6094
if err != nil {
@@ -76,6 +110,8 @@ func Load(filepath string) (Map, error) {
76110
return properties, nil
77111
}
78112

113+
// LoadFromSlice reads a properties file from an array of string
114+
// and makes a Map out of it
79115
func LoadFromSlice(lines []string) (Map, error) {
80116
properties := make(Map)
81117

@@ -109,6 +145,8 @@ func (m Map) parseLine(line string) error {
109145
return nil
110146
}
111147

148+
// SafeLoad is like Load, except that it returns an empty Map if the specified
149+
// file doesn't exists
112150
func SafeLoad(filepath string) (Map, error) {
113151
_, err := os.Stat(filepath)
114152
if os.IsNotExist(err) {
@@ -122,6 +160,38 @@ func SafeLoad(filepath string) (Map, error) {
122160
return properties, nil
123161
}
124162

163+
// FirstLevelOf generates a map-of-Maps using the first level of the hierarchy
164+
// of the current Map. For example the following Map:
165+
//
166+
// properties.Map{
167+
// "uno.name": "Arduino/Genuino Uno",
168+
// "uno.upload.tool": "avrdude",
169+
// "uno.upload.protocol": "arduino",
170+
// "uno.upload.maximum_size": "32256",
171+
// "diecimila.name": "Arduino Duemilanove or Diecimila",
172+
// "diecimila.upload.tool": "avrdude",
173+
// "diecimila.upload.protocol": "arduino",
174+
// "diecimila.bootloader.tool": "avrdude",
175+
// "diecimila.bootloader.low_fuses": "0xFF",
176+
// }
177+
//
178+
// is transformed into the following map-of-Maps:
179+
//
180+
// map[string]Map{
181+
// "uno" : properties.Map{
182+
// "name": "Arduino/Genuino Uno",
183+
// "upload.tool": "avrdude",
184+
// "upload.protocol": "arduino",
185+
// "upload.maximum_size": "32256",
186+
// },
187+
// "diecimila" : properties.Map{
188+
// "name=Arduino Duemilanove or Diecimila
189+
// "upload.tool": "avrdude",
190+
// "upload.protocol": "arduino",
191+
// "bootloader.tool": "avrdude",
192+
// "bootloader.low_fuses": "0xFF",
193+
// }
194+
// }
125195
func (m Map) FirstLevelOf() map[string]Map {
126196
newMap := make(map[string]Map)
127197
for key, value := range m {
@@ -137,10 +207,42 @@ func (m Map) FirstLevelOf() map[string]Map {
137207
return newMap
138208
}
139209

210+
// SubTree extracts a sub Map from an existing map using the first level
211+
// of the keys hierarchy as selector.
212+
// For example the following Map:
213+
//
214+
// properties.Map{
215+
// "uno.name": "Arduino/Genuino Uno",
216+
// "uno.upload.tool": "avrdude",
217+
// "uno.upload.protocol": "arduino",
218+
// "uno.upload.maximum_size": "32256",
219+
// "diecimila.name": "Arduino Duemilanove or Diecimila",
220+
// "diecimila.upload.tool": "avrdude",
221+
// "diecimila.upload.protocol": "arduino",
222+
// "diecimila.bootloader.tool": "avrdude",
223+
// "diecimila.bootloader.low_fuses": "0xFF",
224+
// }
225+
//
226+
// after calling SubTree("uno") will be transformed in:
227+
//
228+
// properties.Map{
229+
// "name": "Arduino/Genuino Uno",
230+
// "upload.tool": "avrdude",
231+
// "upload.protocol": "arduino",
232+
// "upload.maximum_size": "32256",
233+
// },
140234
func (m Map) SubTree(key string) Map {
141235
return m.FirstLevelOf()[key]
142236
}
143237

238+
// ExpandPropsInString use the Map to replace values into a format string.
239+
// The format string should contains markers between braces, for example:
240+
//
241+
// "The selected upload protocol is {upload.protocol}."
242+
//
243+
// Each marker is replaced by the corresponding value of the Map.
244+
// The values in the Map may contains other markers, they are evaluated
245+
// recursively.
144246
func (m Map) ExpandPropsInString(str string) string {
145247
replaced := true
146248
for i := 0; i < 10 && replaced; i++ {
@@ -154,6 +256,8 @@ func (m Map) ExpandPropsInString(str string) string {
154256
return str
155257
}
156258

259+
// Merge merges a Map into this one. Each key/value of the merged Maps replaces
260+
// the key/value present in the original Map.
157261
func (m Map) Merge(sources ...Map) Map {
158262
for _, source := range sources {
159263
for key, value := range source {
@@ -163,16 +267,21 @@ func (m Map) Merge(sources ...Map) Map {
163267
return m
164268
}
165269

270+
// Clone makes a copy of the Map
166271
func (m Map) Clone() Map {
167272
clone := make(Map)
168273
clone.Merge(m)
169274
return clone
170275
}
171276

277+
// Equals returns true if the current Map contains the same key/value pairs of
278+
// the Map passed as argument.
172279
func (m Map) Equals(other Map) bool {
173280
return reflect.DeepEqual(m, other)
174281
}
175282

283+
// MergeMapsOfProperties merge the map-of-Maps (obtained from the method FirstLevelOf()) into the
284+
// target map-of-Maps.
176285
func MergeMapsOfProperties(target map[string]Map, sources ...map[string]Map) map[string]Map {
177286
for _, source := range sources {
178287
for key, value := range source {
@@ -182,6 +291,8 @@ func MergeMapsOfProperties(target map[string]Map, sources ...map[string]Map) map
182291
return target
183292
}
184293

294+
// DeleteUnexpandedPropsFromString removes all the brace markers "{xxx}" that are not expanded
295+
// into a value using the Map.ExpandPropsInString() method.
185296
func DeleteUnexpandedPropsFromString(str string) string {
186297
rxp := regexp.MustCompile("\\{.+?\\}")
187298
return rxp.ReplaceAllString(str, "")

0 commit comments

Comments
 (0)