refactor section file generation to make it more generic

This commit is contained in:
Michael Becker 2024-08-24 15:50:28 -04:00
parent d6eb3868ec
commit 8c138247e0
5 changed files with 204 additions and 73 deletions

View File

@ -90,7 +90,7 @@ class Yaml2Mcl:
exportEntitiesFileName = "entities.cs" exportEntitiesFileName = "entities.cs"
print("export entities to file: '" + exportEntitiesFileName + "'") print("export entities to file: '" + exportEntitiesFileName + "'")
manager.save_entities_to_file(exportEntitiesFileName) manager.save_entities_to_file(exportEntitiesFileName, outputFileName)
return True return True

View File

@ -115,78 +115,17 @@ class MemoryLibraryManager (MochaLibraryManager):
guids = guid_db.to_list() guids = guid_db.to_list()
f = open(self.filename, "wb") from .sectionfile import SectionFile, Section, GuidSection, InstancesSection, AttributesSection, RelationshipsSection, StringTableSection, ResourcesSection
f.write("MCX!".encode('utf-8')) f = SectionFile("MCX!", 2.0, 15)
f.open(self.filename)
# version f.sections.append(GuidSection("GUIDTable", guids))
import struct f.sections.append(InstancesSection("Instances", insts))
ba = bytearray(struct.pack("f", 2.0)) f.sections.append(AttributesSection("Attributes", atts))
f.write(ba) f.sections.append(RelationshipsSection("Relationships", rels))
f.sections.append(StringTableSection("StringTable", strs_db))
f.sections.append(ResourcesSection("Resources", rsrc_db))
section_count = 6 f.save()
# section count
f.write(int.to_bytes(section_count, 4, 'little'))
# sections = [ (offset, length) ]
sections = [ ("GUIDTable", guids, 16), ("Instances", insts, 16), ("Attributes", atts, 12), ("Relationships", rels, 12), ("StringTable", strs_db, None), ("Resources", rsrc_db, None) ]
offset = 12 + (section_count * 32)
lastLength = 0
for (name, sect, item_len) in sections:
offset += lastLength
length = 0
if item_len is None:
if sect == strs_db:
for itm in sect:
# FIXME: hard code for z-strings
length += len(itm) + 1
elif sect == rsrc_db:
for itm in sect:
length += len(itm)
else:
length = item_len * len(sect)
f.write(str(name).ljust(16, '\0').encode("utf-8"))
f.write(int.to_bytes(offset, 4, 'little'))
f.write(int.to_bytes(length, 4, 'little'))
f.write(int.to_bytes(len(sect), 4, 'little'))
f.write(int.to_bytes(0, 4, 'little')) # reserved or padding
lastLength = length
# guids
for guid in guids:
f.write(guid.to_bytes())
# instances
for (gi, cgi, ckey, ikey) in insts:
f.write(int.to_bytes(cgi, 4, 'little'))
f.write(int.to_bytes(gi, 4, 'little'))
f.write(int.to_bytes(ckey, 4, 'little'))
f.write(int.to_bytes(ikey, 4, 'little'))
# attributes
for (srci, atti, vali, edate) in atts:
f.write(int.to_bytes(srci, 4, 'little'))
f.write(int.to_bytes(atti, 4, 'little'))
f.write(int.to_bytes(vali, 4, 'little'))
# relationships
for (srci, reli, tgti, edate) in rels:
f.write(int.to_bytes(srci, 4, 'little'))
f.write(int.to_bytes(reli, 4, 'little'))
f.write(int.to_bytes(tgti, 4, 'little'))
# string table
for strz in strs_db:
f.write(strz.encode("utf-8"))
f.write(int.to_bytes(0, 1, 'little'))
# resource table
for rsrc in rsrc_db:
f.write(rsrc)
f.close()
print ("processed " + str(len(self.instance_ops)) + " instances, " + str(len(self.attribute_ops)) + " attributes, and " + str(len(self.relationship_ops)) + " relationships") print ("processed " + str(len(self.instance_ops)) + " instances, " + str(len(self.attribute_ops)) + " attributes, and " + str(len(self.relationship_ops)) + " relationships")

View File

@ -0,0 +1,108 @@
# Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
#
# This file is part of yaml2mcl.
#
# yaml2mcl 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 3 of the License, or
# (at your option) any later version.
#
# yaml2mcl 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 yaml2mcl. If not, see <https://www.gnu.org/licenses/>.
class Section:
def __init__(self, name : str, data, count : int):
self.name = name
self.data = data
self.count = count
def get_length(self):
return self.count * len(self.data)
def write_data(self, f):
pass
class GuidSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 16)
def write_data(self, f):
for guid in self.data:
f.write(guid.to_bytes())
class InstancesSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 16)
def write_data(self, f):
for (gi, cgi, ckey, ikey) in self.data:
f.write(int.to_bytes(cgi, 4, 'little'))
f.write(int.to_bytes(gi, 4, 'little'))
f.write(int.to_bytes(ckey, 4, 'little'))
f.write(int.to_bytes(ikey, 4, 'little'))
class AttributesSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 12)
def write_data(self, f):
for (srci, atti, vali, edate) in self.data:
f.write(int.to_bytes(srci, 4, 'little'))
f.write(int.to_bytes(atti, 4, 'little'))
f.write(int.to_bytes(vali, 4, 'little'))
class RelationshipsSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 12)
def write_data(self, f):
for (srci, reli, tgti, edate) in self.data:
f.write(int.to_bytes(srci, 4, 'little'))
f.write(int.to_bytes(reli, 4, 'little'))
f.write(int.to_bytes(tgti, 4, 'little'))
class StringTableSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 0)
def get_length(self):
length = 0
for item in self.data:
length += len(item) + 1
return length
def write_data(self, f):
for item in self.data:
f.write(item.encode("utf-8"))
f.write(int.to_bytes(0, 1, 'little'))
class ResourcesSection (Section):
def __init__(self, name : str, data : list):
Section.__init__(self, name, data, 0)
def get_length(self):
length = 0
for item in self.data:
length += len(item)
return length
def write_data(self, f):
for rsrc in self.data:
f.write(rsrc)

View File

@ -0,0 +1,68 @@
# Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
#
# This file is part of yaml2mcl.
#
# yaml2mcl 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 3 of the License, or
# (at your option) any later version.
#
# yaml2mcl 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 yaml2mcl. If not, see <https://www.gnu.org/licenses/>.
from .Section import Section
class SectionFile:
def __init__(self, signature : str = None, version : float = 1.0, flags : int = 0):
self.signature = signature
self.sections = [ ]
self.version = version
self.flags = flags
def add_section(self, section : Section):
self.sections.append(section)
def open(self, filename : str):
self.filename = filename
def save(self):
f = open(self.filename, 'wb')
if self.signature is not None:
f.write(self.signature.encode('utf-8'))
import struct
ba = bytearray(struct.pack("f", self.version))
f.write(ba)
f.write(int.to_bytes(self.flags, 4, 'little'))
section_count = len(self.sections)
f.write(int.to_bytes(section_count, 4, 'little'))
offset = 16 + (section_count * 32)
lastLength = 0
for sect in self.sections:
offset += lastLength
length = sect.get_length()
f.write(str(sect.name).ljust(16, '\0').encode("utf-8"))
f.write(int.to_bytes(offset, 4, 'little'))
f.write(int.to_bytes(length, 4, 'little'))
f.write(int.to_bytes(len(sect.data), 4, 'little'))
f.write(int.to_bytes(0, 4, 'little')) # reserved or padding
lastLength = length
for sect in self.sections:
sect.write_data(f)
f.close()

View File

@ -0,0 +1,16 @@
# Copyright 2024 Michael Becker <alcexhim@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .SectionFile import SectionFile
from .Section import Section, GuidSection, InstancesSection, AttributesSection, RelationshipsSection, StringTableSection, ResourcesSection