Class: Pangrid::AcrossLiteBinary
- Includes:
- AcrossLiteUtils
- Defined in:
- lib/pangrid/plugins/acrosslite.rb
Overview
Binary format
Constant Summary collapse
- DESCRIPTION =
"AcrossLite binary format (.puz)"
- HEADER_FORMAT =
"v A12 v V2 A4 v2 A12 c2 v3"
- HEADER_CHECKSUM_FORMAT =
"c2 v3"
- EXT_HEADER_FORMAT =
"A4 v2"
- EXTENSIONS =
%w(LTIM GRBS RTBL GEXT)
- FILE_MAGIC =
"ACROSS&DOWN\0"
Constants inherited from Plugin
Plugin::FAILED, Plugin::MISSING_DEPS, Plugin::REGISTRY
Instance Attribute Summary collapse
-
#cs ⇒ Object
crossword, checksums.
-
#xw ⇒ Object
crossword, checksums.
Instance Method Summary collapse
-
#initialize ⇒ AcrossLiteBinary
constructor
A new instance of AcrossLiteBinary.
- #read(data) ⇒ Object
- #write(xw) ⇒ Object
Methods included from AcrossLiteUtils
#empty_fill, #pack_solution, #unpack_solution
Methods inherited from Plugin
class_to_name, get, inherited, list_all, load_all, load_plugin
Methods included from PluginUtils
Constructor Details
#initialize ⇒ AcrossLiteBinary
Returns a new instance of AcrossLiteBinary.
86 87 88 89 90 |
# File 'lib/pangrid/plugins/acrosslite.rb', line 86 def initialize @xw = XWord.new @cs = OpenStruct.new @xw.extensions = [] end |
Instance Attribute Details
#cs ⇒ Object
crossword, checksums
76 77 78 |
# File 'lib/pangrid/plugins/acrosslite.rb', line 76 def cs @cs end |
#xw ⇒ Object
crossword, checksums
76 77 78 |
# File 'lib/pangrid/plugins/acrosslite.rb', line 76 def xw @xw end |
Instance Method Details
#read(data) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/pangrid/plugins/acrosslite.rb', line 92 def read(data) s = data.force_encoding("ISO-8859-1") i = s.index(FILE_MAGIC) check("Could not recognise AcrossLite binary file") { i } # read the header h_start, h_end = i - 2, i - 2 + 0x34 header = s[h_start .. h_end] cs.global, _, cs.cib, cs.masked_low, cs.masked_high, xw.version, _, cs.scrambled, _, xw.width, xw.height, xw.n_clues, xw.puzzle_type, xw.scrambled_state = header.unpack(HEADER_FORMAT) # solution and fill = blocks of w*h bytes each size = xw.width * xw.height xw.solution = unpack_solution xw, s[h_end, size] xw.fill = s[h_end + size, size] s = s[h_end + 2 * size .. -1] # title, author, copyright, clues * n, notes = zero-terminated strings xw.title, xw., xw.copyright, *xw.clues, xw.notes, s = s.split("\0", xw.n_clues + 5) # extensions: 8-byte header + len bytes data + \0 while (s.length > 8) do e = OpenStruct.new e.section, e.len, e.checksum = s.unpack(EXT_HEADER_FORMAT) check("Unrecognised extension #{e.section}") { EXTENSIONS.include? e.section } size = 8 + e.len + 1 break if s.length < size e.data = s[8 ... size] self.send(:"read_#{e.section.downcase}", e) xw.extensions << e s = s[size .. -1] end # verify checksums check("Failed checksum") { checksums == cs } process_extensions unpack_clues xw end |
#write(xw) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/pangrid/plugins/acrosslite.rb', line 139 def write(xw) @xw = xw # fill in some fields that might not be present (checksums needs this) pack_clues xw.clues = xw.clues.map(&:to_s) xw.n_clues = xw.clues.length xw.fill ||= empty_fill(xw) xw.puzzle_type ||= 1 xw.scrambled_state ||= 0 xw.version = "1.3" xw.notes ||= "" xw.extensions ||= [] xw.title ||= "" xw. ||= "" xw.copyright ||= "" # extensions xw.encode_rebus! if not xw.rebus.empty? # GRBS e = OpenStruct.new e.section = "GRBS" e.grid = xw.to_array({:black => 0, :null => 0}) {|s| s.rebus? ? s.solution.symbol.to_i : 0 }.flatten xw.extensions << e # RTBL e = OpenStruct.new e.section = "RTBL" e.rebus = {} xw.rebus.each do |long, (k, short)| e.rebus[k] = [long, short] end xw.extensions << e end # calculate checksums @cs = checksums h = [cs.global, FILE_MAGIC, cs.cib, cs.masked_low, cs.masked_high, xw.version + "\0", 0, cs.scrambled, "\0" * 12, xw.width, xw.height, xw.n_clues, xw.puzzle_type, xw.scrambled_state] header = h.pack(HEADER_FORMAT) strings = [xw.title, xw., xw.copyright] + xw.clues + [xw.notes] strings = strings.map {|x| x + "\0"}.join [header, pack_solution(xw), xw.fill, strings, write_extensions].map {|x| x.force_encoding("ISO-8859-1") }.join end |