Class: Palm::PDB
- Inherits:
-
Object
- Object
- Palm::PDB
- Defined in:
- lib/palm/pdb.rb
Overview
PDB handles reading and writing raw Palm PDB records and resources. For most cases, users will probably want to extend this class class, overriding pack_entry and unpack_entry to support their record types.
Records are simply stored as an array in data
, so polish up on your enumerable tricks. The created_at
, modified_at
, and backed_up_at
attributes are all stored as Times. Note that modified_at
is not automatically updated.
Direct Known Subclasses
Constant Summary collapse
- HEADER_LENGTH =
Size of database header
32+2+2+(9*4)
- RECORD_INDEX_HEADER_LEN =
Size of record index header
6
- INDEX_RECORD_LENGTH =
Length of record index entry
8
- INDEX_RESOURCE_LENGTH =
Length of resource index entry
10
- ATTRIBUTE_CODES =
{ "resource" => 0x0001, "read-only" => 0x0002, "AppInfo dirty" => 0x0004, "backup" => 0x0008, "OK newer" => 0x0010, "reset" => 0x0020, "launchable" => 0x0200, "open" => 0x8000, # PalmOS 5.0 attribute names "ResDB" => 0x0001, "ReadOnly" => 0x0002, "AppInfoDirty" => 0x0004, "Backup" => 0x0008, "OKToInstallNewer" => 0x0010, "ResetAfterInstall"=> 0x0020, "LaunchableData" => 0x0200, "Recyclable" => 0x0400, "Bundle" => 0x0800, "Open" => 0x8000, }
Instance Attribute Summary collapse
-
#attributes ⇒ Object
Returns the value of attribute attributes.
-
#backed_up_at ⇒ Object
Returns the value of attribute backed_up_at.
-
#created_at ⇒ Object
Returns the value of attribute created_at.
-
#creator ⇒ Object
Returns the value of attribute creator.
-
#data ⇒ Object
Returns the value of attribute data.
-
#modified_at ⇒ Object
Returns the value of attribute modified_at.
-
#modnum ⇒ Object
Returns the value of attribute modnum.
-
#name ⇒ Object
Returns the value of attribute name.
-
#type ⇒ Object
Returns the value of attribute type.
-
#unique_id_seed ⇒ Object
Returns the value of attribute unique_id_seed.
-
#version ⇒ Object
Returns the value of attribute version.
Instance Method Summary collapse
-
#initialize(from = nil) ⇒ PDB
constructor
Creates a new PDB.
-
#load(io) ⇒ Object
Loads the PDB from the given IO source.
-
#load_file(path) ⇒ Object
Loads the PDB from a file path.
-
#resource? ⇒ Boolean
Returns true if the PDB is a set of resources, false if it is a set of records.
-
#write(io) ⇒ Object
Writes PDB to an IO object.
-
#write_file(path) ⇒ Object
Writes to the given path.
Constructor Details
#initialize(from = nil) ⇒ PDB
Creates a new PDB. If from
is passed a String, a file will be loaded from that path (see load_file
). If a IO object is passed in, then it will be used to load the palm data (see load
).
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/palm/pdb.rb', line 68 def initialize(from = nil) @attributes = {} @data = [] @appinfo_block = nil @sort_block = nil @backed_up_at = @created_at = @modified_at = Time.now case from when NilClass now = Time.now @created_at = now @modified_at = now @version = 0 @modnum = 0 @type = "\0\0\0\0" @creator = "\0\0\0\0" @unique_id_seed = 0 when String load(open(from)) when IO load(from) else raise ArgumentError.new("Unknown value to load from #{from.inspect}. Use a String or IO object.") end end |
Instance Attribute Details
#attributes ⇒ Object
Returns the value of attribute attributes.
31 32 33 |
# File 'lib/palm/pdb.rb', line 31 def attributes @attributes end |
#backed_up_at ⇒ Object
Returns the value of attribute backed_up_at.
32 33 34 |
# File 'lib/palm/pdb.rb', line 32 def backed_up_at @backed_up_at end |
#created_at ⇒ Object
Returns the value of attribute created_at.
32 33 34 |
# File 'lib/palm/pdb.rb', line 32 def created_at @created_at end |
#creator ⇒ Object
Returns the value of attribute creator.
33 34 35 |
# File 'lib/palm/pdb.rb', line 33 def creator @creator end |
#data ⇒ Object
Returns the value of attribute data.
35 36 37 |
# File 'lib/palm/pdb.rb', line 35 def data @data end |
#modified_at ⇒ Object
Returns the value of attribute modified_at.
32 33 34 |
# File 'lib/palm/pdb.rb', line 32 def modified_at @modified_at end |
#modnum ⇒ Object
Returns the value of attribute modnum.
33 34 35 |
# File 'lib/palm/pdb.rb', line 33 def modnum @modnum end |
#name ⇒ Object
Returns the value of attribute name.
31 32 33 |
# File 'lib/palm/pdb.rb', line 31 def name @name end |
#type ⇒ Object
Returns the value of attribute type.
33 34 35 |
# File 'lib/palm/pdb.rb', line 33 def type @type end |
#unique_id_seed ⇒ Object
Returns the value of attribute unique_id_seed.
34 35 36 |
# File 'lib/palm/pdb.rb', line 34 def unique_id_seed @unique_id_seed end |
#version ⇒ Object
Returns the value of attribute version.
31 32 33 |
# File 'lib/palm/pdb.rb', line 31 def version @version end |
Instance Method Details
#load(io) ⇒ Object
Loads the PDB from the given IO source.
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 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/palm/pdb.rb', line 107 def load(io) # Set to binary mode for windows environment io.binmode if io.respond_to? :binmode start_postion = io.pos io.seek(0, IO::SEEK_END) io_size = io.pos io.seek(start_postion) appinfo_offset, sort_offset = unpack_header(io.read(HEADER_LENGTH)) # parse the record index record_index = io.read(RECORD_INDEX_HEADER_LEN) next_index, record_count = record_index.unpack("N n") # load the indexes, gather information about offsets and # record lengths indexes = nil if resource? indexes = load_resource_index(io, next_index, record_count) else indexes = load_record_index(io, next_index, record_count) end # Add the final offset as a Datablock for the end of the file indexes << DataBlock.new(io_size, 0) # Fill in the lengths for each of these index entries indexes.each_cons(2){|starts, ends| starts.record_length = ends.offset - starts.offset } # Calculate where the data starts (or end of file if empty) data_offset = indexes.first.offset # Pop the last entry back off. We pushed it on make it easier to calculate the lengths # of each entry. indexes.pop # Load optional chunks load_appinfo_block(io, appinfo_offset, sort_offset, data_offset) if appinfo_offset > 0 load_sort_block(io, sort_offset, data_offset) if sort_offset > 0 # Load data load_data(io, indexes) io.close end |
#load_file(path) ⇒ Object
Loads the PDB from a file path
100 101 102 103 104 |
# File 'lib/palm/pdb.rb', line 100 def load_file(path) open path, "r" do |io| load io end end |
#resource? ⇒ Boolean
Returns true if the PDB is a set of resources, false if it is a set of records
95 96 97 |
# File 'lib/palm/pdb.rb', line 95 def resource? @attributes['resource'] || @attributes['ResDB'] end |
#write(io) ⇒ Object
Writes PDB to an IO object
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/palm/pdb.rb', line 270 def write(io) io.binmode if io.respond_to? :binmode # Track the current offset for each section offset_position = HEADER_LENGTH + 2 #(2: Index Header length) index_length = RECORD_INDEX_HEADER_LEN + @data.length * (resource? ? INDEX_RESOURCE_LENGTH : INDEX_RECORD_LENGTH ) offset_position += index_length # Advance for the index packed_entries = @data.map{|e| pack_entry(e)} packed_app_info = pack_app_info_block() packed_sort = pack_sort_block() # Calculate AppInfo block offset app_info_offset = 0 if packed_app_info and !packed_app_info.empty? app_info_offset = offset_position offset_position += packed_app_info.length # Advance for the app_info_block end # Calculate sort block offset sort_offset = 0 if packed_sort and !packed_sort.empty? sort_offset = offset_position offset_position += packed_sort.length # Advance for the sort_block end packed_header = pack_header(app_info_offset, sort_offset) index_header = [0, @data.length ].pack "N n" packed_index = @data.zip(packed_entries).map do |entry, packed| index = nil if resource? index = [entry.record_type, entry.record_id, offset_position].pack "a4 n N" else index = [ offset_position, entry.packed_attributes, (entry.record_id >> 16) & 0xff, (entry.record_id >> 8) & 0xff, entry.record_id & 0xff ].pack "N C C3" end offset_position += packed.length index end # Write to IO stream io << packed_header io << index_header io << packed_index.join io << "\0\0" # 2 null byte separator io << @app_info_block unless app_info_offset == 0 io << @sort_block unless sort_offset == 0 io << packed_entries.join end |
#write_file(path) ⇒ Object
Writes to the given path
263 264 265 266 267 |
# File 'lib/palm/pdb.rb', line 263 def write_file(path) open(path, "w") do |io| write io end end |