nwn-lib 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -136,3 +136,14 @@ Bernhard Stoeckner <elven@swordcoast.net> (2):
136
136
  NWN::Erf: basic reading/writing library + tar-like binary
137
137
  add tlk.rb to nwn/all.rb
138
138
  0.4.3-rel
139
+
140
+ === 0.4.4
141
+ Bernhard Stoeckner (7):
142
+ bin/nwn-gff: guess outfile format based on extension
143
+ erf: do not fail on misaligned strings, print warning instead
144
+ bin/nwn-erf: compat mode with tar, options can be without dashes
145
+ API: Add some helpers for creating Gff elements
146
+ scripting: satisfy: return object as-is when no conditions are given
147
+ bin/nwn-erf: -vt: move column type before filename
148
+ erf: fix loctable reading breaking on more than one locstr
149
+ 0.4.4-rel
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "nwn-lib"
12
- VERS = "0.4.3"
12
+ VERS = "0.4.4"
13
13
  CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
14
14
  RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
15
15
  'nwn-lib: a ruby library for accessing NWN resource files', \
@@ -10,6 +10,9 @@ $type = 'ERF'
10
10
  $allow_duplicates = false
11
11
  $descriptions = {}
12
12
 
13
+ # tar-compat mode: first argument is options if no dash is specified.
14
+ ARGV[0] = "-" + ARGV[0] if ARGV.size > 0 && ARGV[0][0] != ?-
15
+
13
16
  begin OptionParser.new do |o|
14
17
  o.banner = "Usage: nwn-erf <options> [FILEs] ..."
15
18
 
@@ -80,7 +83,6 @@ begin OptionParser.new do |o|
80
83
  end.parse!
81
84
  rescue => ee
82
85
  $stderr.puts ee.to_s
83
- $stderr.puts ee.backtrace.join("\n")
84
86
  exit 1
85
87
  end
86
88
 
@@ -105,15 +107,15 @@ case $action
105
107
  when :t
106
108
  input {|f|
107
109
  erf = NWN::Erf::Erf.new(f)
108
- $stderr.puts "# %-4s %14s %16s %-10s %s" % %w{type offset size date filename} if $verbose
110
+ $stderr.puts "# %14s %16s %-10s %-4s %s" % %w{offset size date type filename} if $verbose
109
111
  erf.content.each {|c|
110
112
  if !$verbose
111
113
  $stderr.puts "%s" % [c.filename]
112
114
  else
113
- $stderr.puts "%4d %16d %16d %10s %s" % [
114
- c.res_type, c.offset, c.size,
115
+ $stderr.puts "%16d %16d %10s %4d %s" % [
116
+ c.offset, c.size,
115
117
  Date.ordinal(1900 + erf.year, erf.day_of_year).strftime("%Y-%m-%d"),
116
- c.filename
118
+ c.res_type, c.filename
117
119
  ]
118
120
  end
119
121
  }
@@ -36,7 +36,7 @@ begin OptionParser.new do |o|
36
36
  end
37
37
  o.on "-k", "--outfile-format FORMAT", [:in, :none] + NWN::Gff::FileFormats,
38
38
  "Output format (#{([:none, :in] + NWN::Gff::FileFormats).join(', ')})",
39
- "(default: in - same as input)" do |f|
39
+ "(default: in when stdout, try to guess based on extension otherwise)" do |f|
40
40
  $options[:outformat] = f
41
41
  end
42
42
 
@@ -107,7 +107,13 @@ if :auto == $options[:informat]
107
107
  $options[:informat]
108
108
  end
109
109
 
110
- $options[:outformat] = $options[:informat] if :in == $options[:outformat]
110
+ if $options[:outfile] == "-"
111
+ $options[:outformat] = $options[:informat] if :in == $options[:outformat]
112
+ elsif :in == $options[:outformat]
113
+ $options[:outformat] = NWN::Gff.guess_file_format($options[:outfile])
114
+ fail "Cannot guess outfile format from filename, specify with -k." unless
115
+ $options[:outformat]
116
+ end
111
117
 
112
118
  vputs "Reading: #{$options[:infile]}"
113
119
  data_in = $options[:infile] == '-' ? $stdin.read : IO.read($options[:infile])
@@ -235,14 +235,16 @@ module NWN
235
235
  raise IOError, "Cannot read locstr list" unless
236
236
  locstr.size == locstr_size
237
237
 
238
- locstrs = locstr.unpack("V V/a*" * locstr_count)
239
- locstrs.each_slice(3) {|lid, strsz, str|
240
- raise IOError,
241
- "Cannot read localized strings table: string size not met (want: #{strsz}, got #{str.size})" if
242
- str.size != strsz
238
+ for lstr in 0...locstr_count do
239
+ lid, strsz = locstr.unpack("V V")
240
+ str = locstr.unpack("a#{strsz}")[0]
241
+ $stderr.puts "Expected string size does not match actual string size (want: #{strsz}, got #{str.size} of #{str.inspect})" if
242
+ strsz != str.size
243
243
  @localized_strings[lid] = str
244
- }
245
-
244
+ locstr = locstr[8 + str.size .. -1]
245
+ raise IOError, "locstr table does not contain enough entries (want: #{locstr_count}, got: #{lstr + 1})" if locstr.nil? &&
246
+ lstr + 1 < locstr_count
247
+ end
246
248
 
247
249
  keylist_entry_size = @filename_length + 4 + 2 + 2
248
250
  keylist = @io.read(keylist_entry_size * entry_count)
@@ -16,6 +16,14 @@ module NWN::Gff::Field
16
16
  # This is set internally by Gff::Reader on load.
17
17
  attr_accessor :parent
18
18
 
19
+ # Create a new NWN::Gff::Field
20
+ def self.new label, type, value
21
+ s = {}.extend(self)
22
+ s['label'], s['type'], s['value'] = label, type, value
23
+ s.extend_meta_classes
24
+ s
25
+ end
26
+
19
27
  def field_type
20
28
  self['type']
21
29
  end
@@ -1,2 +1,53 @@
1
1
  module NWN::Gff::List
2
+
3
+ # Add a new struct member to this list.
4
+ # You can either add an existing struct to this list
5
+ # (which will reparent it by setting .element), or specify
6
+ # a new struct with a block, or both:
7
+ #
8
+ # root = Gff::Struct.new 0xffffffff, "UTI", "V3.2"
9
+ # list = root.add_list 'test', []
10
+ # list.add_struct 1 do |l|
11
+ # l.add_byte 'inner_test', 5
12
+ # l.add_cexolocstr 'exolocstr', { 0 => 'Hello', 4 => 'Hallo' }
13
+ # end
14
+ # y root
15
+ #
16
+ # results in:
17
+ # --- !nwn-lib.elv.es,2008-12/struct
18
+ # __data_type: UTI
19
+ # __struct_id: 4294967295
20
+ # test:
21
+ # type: :list
22
+ # value:
23
+ # - !nwn-lib.elv.es,2008-12/struct
24
+ # __data_type: UTI/test
25
+ # __struct_id: 1
26
+ # exolocstr:
27
+ # type: :cexolocstr
28
+ # value:
29
+ # 0: Hello
30
+ # 4: Hallo
31
+ # inner_test: {type: :byte, value: 5}}
32
+ def add_struct struct_id_or_struct = 0, &block
33
+ struct = case struct_id_or_struct
34
+ when Integer
35
+ s = NWN::Gff::Struct.new
36
+ s.struct_id = struct_id_or_struct
37
+ s
38
+
39
+ when NWN::Gff::Struct
40
+ struct_id_or_struct
41
+
42
+ else
43
+ raise ArgumentError, "specify either a struct_id or an existing struct"
44
+ end
45
+
46
+ struct.element = self
47
+
48
+ yield(struct) if block_given?
49
+
50
+ self.v << struct
51
+ struct
52
+ end
2
53
  end
@@ -18,17 +18,68 @@ module NWN::Gff::Struct
18
18
  # The field this struct is value of.
19
19
  # It is most likely a Field of :list, or
20
20
  # :nil if it is the root struct.
21
- attr_accessor :element
21
+ # Setting this to a value detaches this struct from
22
+ # the old parent (though the old parent Field may still
23
+ # point to this object).
24
+ attr_reader :element
22
25
 
23
26
  # Returns the path to this struct (which is usually __data_type)
24
27
  def path
25
28
  @data_type.to_s
26
29
  end
27
30
 
31
+ def element= e #:nodoc:
32
+ @element = e
33
+ @data_type = self.element.parent.path + "/" + self.element.l
34
+ end
35
+
28
36
  # Dump this struct as GFF binary data.
29
37
  #
30
38
  # Optionally specify data_type and data_version
31
39
  def to_gff data_type = nil
32
40
  NWN::Gff::Writer.dump(self, data_type)
33
41
  end
42
+
43
+ # Create a new struct.
44
+ # Usually, you can leave out data_type and data_version for non-root structs,
45
+ # because that will be guess-inherited based on the existing associations.
46
+ def self.new struct_id = 0xffffffff, data_type = nil, data_version = nil
47
+ s = {}.extend(self)
48
+ s.struct_id = struct_id
49
+ s.data_type = data_type
50
+ s.data_version = data_version
51
+ s
52
+ end
53
+
54
+ # Create a new field.
55
+ # Alternatively, you can use the shorthand methods:
56
+ # add_#{type} - add_int, add_byte, ..
57
+ # For example:
58
+ # some_struct.add_field 'ID', :byte, 5
59
+ # is equivalent to:
60
+ # some_struct.add_byte 'ID', 5
61
+ def add_field label, type, value, &block
62
+ self[label] = NWN::Gff::Field.new(label, type, value)
63
+ self[label].parent = self
64
+ if block_given?
65
+ yield(self[label])
66
+ end
67
+ self[label]
68
+ end
69
+
70
+ #:nodoc:
71
+ def method_missing meth, *av, &block
72
+ if meth.to_s =~ /^add_(.+)$/
73
+ if NWN::Gff::Types.index($1.to_sym)
74
+ av.size == 2 or super
75
+ t = $1.to_sym
76
+ f = add_field(av[0], t, av[1], &block)
77
+ return f
78
+ else
79
+ super
80
+ end
81
+ end
82
+
83
+ super
84
+ end
34
85
  end
@@ -76,6 +76,9 @@ module NWN::Gff::Scripting
76
76
  #
77
77
  # Returns the object that satisfies the asked-for conditions,
78
78
  # or nil if none can be given.
79
+ #
80
+ # If only a filename/string is given and no further arguments,
81
+ # the read object will be returned as-is.
79
82
  def satisfy *what
80
83
  if $standalone
81
84
  fn = what.shift
@@ -95,6 +98,8 @@ module NWN::Gff::Scripting
95
98
  obj = self
96
99
  end
97
100
 
101
+ return obj if what.size == 1
102
+
98
103
  what.each {|w|
99
104
  case w
100
105
  when Class, Module
@@ -108,7 +113,6 @@ module NWN::Gff::Scripting
108
113
  return obj if obj.field_type.to_sdowncase == w.to_s.downcase
109
114
  end
110
115
  end
111
-
112
116
  }
113
117
 
114
118
  return nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nwn-lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernhard Stoeckner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-06 00:00:00 +01:00
12
+ date: 2009-03-09 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15