252 lines
6.4 KiB
Plaintext
252 lines
6.4 KiB
Plaintext
# uci
|
|
import file
|
|
# native
|
|
import string
|
|
import json
|
|
|
|
# really a a nested map designe to work like a javascript object with . notation
|
|
class Object
|
|
var _obj
|
|
var _autosave # will save object(map) whenever changes are made, default: false
|
|
var _autoload # if true will attempt to load from file on init, default: true
|
|
var _status
|
|
var file # attached file instance
|
|
var _deep # depth to follow nested maps, default = -1 which mean walk until no more
|
|
|
|
# forbidden key names
|
|
# any key starting with _
|
|
# init
|
|
# member
|
|
# setmember
|
|
# assign
|
|
# retrieve
|
|
# load
|
|
# save
|
|
# get
|
|
# set
|
|
# file
|
|
# filename
|
|
# exporti
|
|
# importi
|
|
|
|
# for passing only opts must set obj to {} or nil, e.g. (nil,{'autosave':true})
|
|
def init(obj,filename,opts)
|
|
if (type(obj) == 'string')
|
|
if debug[3] print('no object passed a filename was passed') end
|
|
opts = filename
|
|
filename = obj
|
|
obj = nil
|
|
end
|
|
if isinstance(filename, map)
|
|
opts = filename
|
|
filename = nil
|
|
end
|
|
if ! opts opts = {} end
|
|
self.assign(self._isMap(obj,true)) # will set to empty map if obj is nil
|
|
if filename
|
|
if debug[3] print('filename passsed, adding file instance', filename) end
|
|
self.file = file(filename,opts.find('ext')) # create file instance
|
|
end
|
|
self._autosave = opts.find('autosave') == nil ? false : opts.find('autosave')
|
|
self._autoload = opts.find('autoload') == nil ? true : opts.find('autoload')
|
|
if self.file
|
|
if self._isMap(obj)
|
|
if self._autosave
|
|
if debug[3] print('autosaving passed object map to', self.file.name()) end
|
|
self.save()
|
|
end
|
|
else
|
|
if self._autoload
|
|
if debug[3] print('autoloading', self.file.name()) end
|
|
return self.load()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
#
|
|
def load (filename)
|
|
if self.file
|
|
if debug[3] print ('loading before', self._obj) end
|
|
var obj = self.file.load(filename)
|
|
if isinstance(obj,map)
|
|
self._obj = obj
|
|
return obj
|
|
# walk object looking for additional maps?
|
|
else
|
|
if debug[3] print ('Warning: Unable to load file or file does not contain a map') end
|
|
end
|
|
if debug[3] print ('loading after',self._obj) end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
def save (filename)
|
|
if self.file
|
|
if debug[3]
|
|
print ('saving', self.file.addext(filename))
|
|
print ('object to be saved', self._obj)
|
|
# print ('contents of current file', self.load(filename))
|
|
end
|
|
self.file.save(self._obj,filename)
|
|
# if debug[3] print ('after saving',self.load(filename)) end
|
|
end
|
|
end
|
|
|
|
|
|
def _isMap (m,init)
|
|
if isinstance(m, map)
|
|
return m
|
|
else
|
|
if init
|
|
return {}
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
|
|
def merge(m,overwrite)
|
|
for k: m.keys()
|
|
if overwrite
|
|
self._obj.setitem(k,m[k])
|
|
else
|
|
self._obj.insert(k,m[k])
|
|
end
|
|
end
|
|
return self._obj
|
|
end
|
|
|
|
def assign(obj)
|
|
if ! obj obj={} end
|
|
if isinstance(obj, map)
|
|
self._obj=obj
|
|
else
|
|
|
|
end
|
|
return self._obj
|
|
end
|
|
|
|
def retrieve()
|
|
return self._obj
|
|
end
|
|
|
|
def exporti(save)
|
|
var obj = self._obj
|
|
if save && self.file
|
|
self.save()
|
|
obj = nil
|
|
end
|
|
return { 'filename': self.filename(), 'obj':obj, 'opts':{'autosave':self._autosave, 'autoload':self._autoload} }
|
|
end
|
|
|
|
def importi(s)
|
|
print ('setting to import',s)
|
|
return Object(s.item('obj'),s.item('filename'),s.item('opts'))
|
|
end
|
|
|
|
def filename()
|
|
if self.file
|
|
return self.file.name()
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
def del(keys)
|
|
self.set(keys,'__remove__')
|
|
end
|
|
|
|
# # sets a nested property
|
|
def set(keys,value)
|
|
|
|
def _set(keys,value,obj)
|
|
if !obj obj = self._obj end
|
|
var key = keys.pop()
|
|
if !obj.find(key)
|
|
obj[key] = {}
|
|
end
|
|
if keys.size()
|
|
return _set(keys,value,obj[key])
|
|
else
|
|
if value == '__remove__'
|
|
obj.remove(key)
|
|
else
|
|
obj[key]=value
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
|
|
if type(keys) == 'string' keys = string.split(keys,".") end
|
|
if !isinstance(keys,list)
|
|
print('ERROR: list of keys not passed', keys)
|
|
return nil
|
|
end
|
|
keys.reverse()
|
|
if debug[3] print('setting',keys,'to',value) end
|
|
if _set(keys,value)
|
|
if self.file && self._autosave self.save() end
|
|
end
|
|
|
|
end
|
|
|
|
def dump(subkey)
|
|
if subkey == nil return json.dump(self.get()) end
|
|
return json.dump(self.get(subkey))
|
|
end
|
|
|
|
# gets a nested property
|
|
def get(keys)
|
|
|
|
if keys == nil return self._obj end
|
|
|
|
def _get(keys,obj)
|
|
if !obj
|
|
obj = self._obj
|
|
end
|
|
var key = keys.pop()
|
|
var _obj = obj.find(key)
|
|
if debug[1]
|
|
print('current key:', key, 'remaining keys:', keys )
|
|
print('current nested object: ',_obj)
|
|
end
|
|
if isinstance(_obj,map)
|
|
if keys.size()
|
|
return _get(keys,_obj)
|
|
else
|
|
return _obj
|
|
end
|
|
else
|
|
return _obj
|
|
end
|
|
end
|
|
|
|
if type(keys) == 'string' keys = string.split(keys,".") end
|
|
if !isinstance(keys,list)
|
|
print('ERROR: list of keys not passed', keys)
|
|
return nil
|
|
end
|
|
keys.reverse()
|
|
if debug[3] print('getting',keys) end
|
|
return _get(keys)
|
|
end
|
|
|
|
# - virtual member getter, if a key does not exists return `nil`-#
|
|
def member(key)
|
|
return self._obj.find(key)
|
|
end
|
|
#- virtual member setter -#
|
|
def setmember(key, value)
|
|
if debug[3]
|
|
print ('setting key=>', key,':', value)
|
|
end
|
|
self._obj[key] = value
|
|
if self._autosave self.save() end
|
|
return self.member(key)
|
|
end
|
|
|
|
end # Object Class
|
|
|
|
var object = module('object')
|
|
object = Object
|
|
return object |