You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yaclog-ksp/yaclog_ksp/cfgnode.py

186 lines
5.7 KiB
Python

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Original: https://github.com/taniwha/cfgnode
# <pep8 compliant>
from yaclog_ksp.script import Script
class ConfigNodeError(Exception):
def __init__(self, fname, line, message):
Exception.__init__(self, "%s:%d: %s" % (fname, line, message))
self.message = "%s:%d: %s" % (fname, line, message)
self.line = line
def cfg_error(self, msg):
raise ConfigNodeError(self.filename, self.line, msg)
class ConfigNode:
def __init__(self):
self.values = []
self.nodes = []
@classmethod
def parse_node(cls, node, script, top=False):
while script.token_available(True):
token_start = script.pos
if script.get_token(True) is None:
break
if script.token == "\xef\xbb\xbf":
continue
if script.token in (top and ['{', '}', '='] or ['{', '=']):
cfg_error(script, "unexpected " + script.token)
if script.token == '}':
return
key = script.token
# print(key,script.line)
while script.token_available(True):
script.get_token(True)
token_end = script.pos
line = script.line
if script.token == '=':
value = ''
if script.token_available(False):
script.get_line()
value = script.token.strip()
node.values.append((key, value, line))
break
elif script.token == '{':
new_node = ConfigNode()
ConfigNode.parse_node(new_node, script, False)
node.nodes.append((key, new_node, line))
break
else:
# cfg_error(script, "unexpected " + script.token)
key = script.text[token_start:token_end]
if not top:
cfg_error(script, "unexpected end of file")
@classmethod
def load(cls, text):
script = Script("", text, "{}=", False)
script.error = cfg_error.__get__(script, Script)
nodes = []
while script.token_available(True):
node = ConfigNode()
ConfigNode.parse_node(node, script, True)
nodes.append(node)
if len(nodes) == 1:
return nodes[0]
else:
return nodes
@classmethod
def loadfile(cls, path):
data = open(path, "rb").read()
try:
contents = "".join(map(lambda b: chr(b), data))
except TypeError:
contents = data
return cls.load(contents)
def get_node(self, key):
for n in self.nodes:
if n[0] == key:
return n[1]
return None
def get_node_line(self, key):
for n in self.nodes:
if n[0] == key:
return n[2]
return None
def get_nodes(self, key):
nodes = []
for n in self.nodes:
if n[0] == key:
nodes.append(n[1])
return nodes
def get_value(self, key):
for v in self.values:
if v[0] == key:
return v[1].strip()
return None
def has_node(self, key):
for n in self.nodes:
if n[0] == key:
return True
return False
def has_value(self, key):
for v in self.values:
if v[0] == key:
return True
return False
def has_value_line(self, key):
for v in self.values:
if v[0] == key:
return v[2]
return None
def get_values(self, key):
values = []
for v in self.values:
if v[0] == key:
values.append(v[1])
return values
def add_node(self, key, node):
self.nodes.append((key, node))
return node
def add_new_node(self, key):
node = ConfigNode()
self.nodes.append((key, node))
return node
def add_value(self, key, value):
self.values.append((key, value))
def set_value(self, key, value):
for i in range(len(self.values)):
if self.values[i][0] == key:
self.values[i] = key, value, 0
return
self.add_value(key, value)
def __str__(self, level=0):
extra = 0
if level >= 0:
extra = 2
segments = [''] * (len(self.values) + len(self.nodes) + extra)
index = 0
if level >= 0:
segments[index] = "{\n"
index += 1
for val in self.values:
segments[index] = "%s%s = %s\n" % (" " * (level + 1), val[0], val[1])
index += 1
for node in self.nodes:
text = node[1].__str__(level + 1)
segments[index] = "%s%s %s\n" % (" " * (level + 1), node[0], text)
index += 1
if level >= 0:
segments[index] = "%s}\n" % (" " * level)
index += 1
return "".join(segments)