fff.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import logging
  2. class FlipperFormatFile:
  3. def __init__(self):
  4. # Storage
  5. self.lines = []
  6. self.cursor = 0
  7. # Logger
  8. self.logger = logging.getLogger("FlipperFormatFile")
  9. def _resetCursor(self):
  10. self.cursor = 0
  11. def nextLine(self):
  12. line = None
  13. while self.cursor < len(self.lines):
  14. temp_line = self.lines[self.cursor].strip()
  15. self.cursor += 1
  16. if len(temp_line) > 0 and not temp_line.startswith("#"):
  17. line = temp_line
  18. break
  19. if line is None:
  20. raise EOFError()
  21. return line
  22. def readKeyValue(self):
  23. line = self.nextLine()
  24. data = line.split(":", 1)
  25. if len(data) != 2:
  26. self.logger.error(f"Incorrectly formated line {self.cursor}: `{line}`")
  27. raise Exception("Unexpected line: not `key:value`")
  28. return data[0].strip(), data[1].strip()
  29. def readKey(self, key: str):
  30. k, v = self.readKeyValue()
  31. if k != key:
  32. raise KeyError(f"Unexpected key {k} != {key}")
  33. return v
  34. def readKeyInt(self, key: str):
  35. value = self.readKey(key)
  36. return int(value) if value else None
  37. def readKeyIntArray(self, key: str):
  38. value = self.readKey(key)
  39. return [int(i) for i in value.split(" ")] if value else None
  40. def readKeyFloat(self, key: str):
  41. value = self.readKey(key)
  42. return float(value) if value else None
  43. def writeLine(self, line: str):
  44. self.lines.insert(self.cursor, line)
  45. self.cursor += 1
  46. def writeKey(self, key: str, value):
  47. if isinstance(value, (str, int, float)):
  48. pass
  49. elif isinstance(value, (list, set)):
  50. value = " ".join(map(str, value))
  51. else:
  52. raise Exception("Unknown value type")
  53. self.writeLine(f"{key}: {value}")
  54. def writeEmptyLine(self):
  55. self.writeLine("")
  56. def writeComment(self, text: str):
  57. self.writeLine(f"# {text}")
  58. def getHeader(self):
  59. if self.cursor != 0 and len(self.lines) == 0:
  60. raise Exception("Can't read header data: cursor not at 0 or file is empty")
  61. # Read Filetype
  62. key, value = self.readKeyValue()
  63. if key != "Filetype":
  64. raise Exception("Invalid Header: missing `Filetype`")
  65. filetype = value
  66. # Read Version
  67. key, value = self.readKeyValue()
  68. if key != "Version":
  69. raise Exception("Invalid Header: missing `Version`")
  70. version = int(value)
  71. return filetype, version
  72. def setHeader(self, filetype: str, version: int):
  73. if self.cursor != 0 and len(self.lines) != 0:
  74. raise Exception("Can't set header data: file is not empty")
  75. self.writeKey("Filetype", filetype)
  76. self.writeKey("Version", version)
  77. def load(self, filename: str):
  78. file = open(filename, "r")
  79. self.lines = file.readlines()
  80. def save(self, filename: str):
  81. file = open(filename, "w")
  82. file.write("\n".join(self.lines))