fdc 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/fdc.rb +3 -8
- data/lib/fdc/compiler.rb +170 -0
- data/lib/fdc/converter.rb +25 -201
- data/lib/fdc/parser.rb +65 -0
- data/lib/fdc/utilities.rb +32 -13
- metadata +3 -1
data/lib/fdc.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
|
-
# Ruby core and stdlib
|
2
|
-
require 'date'
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
# Gems
|
6
|
-
require 'builder'
|
7
|
-
|
8
1
|
# Fdc
|
9
2
|
require 'fdc/utilities'
|
10
3
|
require 'fdc/converter'
|
11
|
-
require 'fdc/exceptions'
|
4
|
+
require 'fdc/exceptions'
|
5
|
+
require 'fdc/parser'
|
6
|
+
require 'fdc/compiler'
|
data/lib/fdc/compiler.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'builder'
|
2
|
+
require 'date'
|
3
|
+
require 'fdc/parser'
|
4
|
+
|
5
|
+
# Compile KML documents from a {Fdc::Parser}
|
6
|
+
class Fdc::Compiler
|
7
|
+
|
8
|
+
# The compiled KML document
|
9
|
+
attr_reader :kml
|
10
|
+
attr_accessor :parser
|
11
|
+
|
12
|
+
# Create a new instance
|
13
|
+
#
|
14
|
+
# @param [Fdc::Parser] parser A parser from which the KML document should be compiled.
|
15
|
+
def initialize(parser)
|
16
|
+
@parser = parser
|
17
|
+
end
|
18
|
+
|
19
|
+
# Compile the KML document from the parsed IGC file.
|
20
|
+
#
|
21
|
+
# @param [String] track_name The name of the KML track
|
22
|
+
# @param [Boolean] clamp Whether the track should be clamped to the ground
|
23
|
+
# @param [Boolean] extrude Whether the track should be extruded to the ground
|
24
|
+
# @param [Boolean] gps Whether GPS altitude information should be used
|
25
|
+
# @raise [RuntimeError] If the supplied parser is not ready
|
26
|
+
def compile(track_name, clamp=false, extrude=false, gps=false)
|
27
|
+
|
28
|
+
raise RuntimeError, "Parser not ready" unless @parser.ready?
|
29
|
+
|
30
|
+
# Build HTML for balloon description
|
31
|
+
html = Builder::XmlMarkup.new(:indent => 2)
|
32
|
+
html.div :style => "width: 250;" do
|
33
|
+
html.p do
|
34
|
+
unless @parser.a_record[3].nil? then
|
35
|
+
html.strong "Device:"
|
36
|
+
html.dfn @parser.a_record[3].strip
|
37
|
+
html.br
|
38
|
+
end
|
39
|
+
end
|
40
|
+
html.p do
|
41
|
+
@parser.h_records.each do |h|
|
42
|
+
if h.include? "PLT" and not h[2].strip.empty? then
|
43
|
+
html.strong "Pilot:"
|
44
|
+
html.dfn h[2].strip
|
45
|
+
html.br
|
46
|
+
end
|
47
|
+
if h.include? "CID" and not h[2].strip.empty? then
|
48
|
+
html.strong "Competition ID:"
|
49
|
+
html.dfn h[2].strip
|
50
|
+
html.br
|
51
|
+
end
|
52
|
+
if h.include? "GTY" and not h[2].strip.empty? then
|
53
|
+
html.strong "Glider:"
|
54
|
+
html.dfn h[2].strip
|
55
|
+
html.br
|
56
|
+
end
|
57
|
+
if h.include? "GID" and not h[2].strip.empty? then
|
58
|
+
html.strong "Glider ID:"
|
59
|
+
html.dfn h[2].strip
|
60
|
+
html.br
|
61
|
+
end
|
62
|
+
if h.include? "CCL" and not h[2].strip.empty? then
|
63
|
+
html.strong "Competition class:"
|
64
|
+
html.dfn h[2].strip
|
65
|
+
html.br
|
66
|
+
end
|
67
|
+
if h.include? "SIT" and not h[2].strip.empty? then
|
68
|
+
html.strong "Site:"
|
69
|
+
html.dfn h[2].strip
|
70
|
+
html.br
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
html.strong "Date:"
|
75
|
+
html.dfn @parser.date_record[3..5].join(".")
|
76
|
+
html.br
|
77
|
+
end
|
78
|
+
|
79
|
+
# Manufacturer-dependent L records
|
80
|
+
case @parser.a_record[1]
|
81
|
+
when "XSX"
|
82
|
+
@parser.l_records.each do |l|
|
83
|
+
if matches = l[1].scan(/(\w*):(-?\d+.?\d+)/) then
|
84
|
+
html.p do
|
85
|
+
matches.each do |match|
|
86
|
+
case match[0]
|
87
|
+
when "MC"
|
88
|
+
html.strong "Max. climb:"
|
89
|
+
html.dfn match[1] << " m/s"
|
90
|
+
html.br
|
91
|
+
when "MS"
|
92
|
+
html.strong "Max. sink:"
|
93
|
+
html.dfn match[1] << " m/s"
|
94
|
+
html.br
|
95
|
+
when "MSP"
|
96
|
+
html.strong "Max. speed:"
|
97
|
+
html.dfn match[1] << " km/h"
|
98
|
+
html.br
|
99
|
+
when "Dist"
|
100
|
+
html.strong "Track distance:"
|
101
|
+
html.dfn match[1] << " km"
|
102
|
+
html.br
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Build KML
|
113
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
114
|
+
xml.instruct!
|
115
|
+
xml.kml "xmlns" => "http://www.opengis.net/kml/2.2", "xmlns:gx" => "http://www.google.com/kml/ext/2.2" do
|
116
|
+
xml.Placemark {
|
117
|
+
xml.name track_name
|
118
|
+
xml.Snippet :maxLines => "2" do
|
119
|
+
xml.text! snippet
|
120
|
+
end
|
121
|
+
xml.description do
|
122
|
+
xml.cdata! html.target!
|
123
|
+
end
|
124
|
+
xml.Style do
|
125
|
+
xml.IconStyle do
|
126
|
+
xml.Icon do
|
127
|
+
xml.href "http://earth.google.com/images/kml-icons/track-directional/track-0.png"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
xml.LineStyle do
|
131
|
+
xml.color "99ffac59"
|
132
|
+
xml.width "4"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
xml.gx:Track do
|
136
|
+
|
137
|
+
clamp ? xml.altitudeMode("clampToGround") : xml.altitudeMode("absolute")
|
138
|
+
extrude ? xml.extrude("1") : xml.extrude("0")
|
139
|
+
|
140
|
+
@parser.b_records.each do |b_record|
|
141
|
+
time = DateTime.new(2000 + @parser.date_record[5].to_i, @parser.date_record[4].to_i, @parser.date_record[3].to_i,
|
142
|
+
b_record[1].to_i, b_record[2].to_i, b_record[3].to_i)
|
143
|
+
xml.when time
|
144
|
+
end
|
145
|
+
@parser.b_records.each do |b_record|
|
146
|
+
coords = Fdc::GeoLocation.to_dec(b_record[5], b_record[4])
|
147
|
+
gps ? coords << b_record[8].to_f : coords << b_record[7].to_f
|
148
|
+
xml.gx :coord, coords.join(" ")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
@kml = xml.target!
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
# Generate Snippet tag content
|
160
|
+
def snippet
|
161
|
+
summary = "Flight"
|
162
|
+
@parser.h_records.each do |h|
|
163
|
+
if h.include? "SIT" and not h[2].strip.empty? then
|
164
|
+
summary << " from #{h[2].strip}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
summary << " on #{@parser.date_record[3..5].join(".")}"
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
data/lib/fdc/converter.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'date'
|
2
1
|
require 'pathname'
|
3
|
-
|
2
|
+
|
4
3
|
require 'fdc/utilities'
|
5
4
|
require 'fdc/exceptions'
|
5
|
+
require 'fdc/parser'
|
6
|
+
require 'fdc/compiler'
|
6
7
|
|
7
|
-
#
|
8
|
+
# Convert IGC Files to KML
|
8
9
|
#
|
9
10
|
# @!attribute [r] kml
|
10
11
|
# @return [String] The KML document
|
@@ -16,11 +17,14 @@ require 'fdc/exceptions'
|
|
16
17
|
# converter.export(output/dir)
|
17
18
|
class Fdc::Converter
|
18
19
|
|
19
|
-
#
|
20
|
+
# Mixins
|
20
21
|
include Fdc::FileLoader
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
include Fdc::FileWriter
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@parser = Fdc::Parser.new
|
26
|
+
@compiler = Fdc::Compiler.new @parser
|
27
|
+
end
|
24
28
|
|
25
29
|
# Load and parse an IGC file from the supplied path.
|
26
30
|
#
|
@@ -29,9 +33,11 @@ class Fdc::Converter
|
|
29
33
|
# @raise [Fdc::FileReadError] If file could not be loaded
|
30
34
|
# @raise [Fdc::FileFormatError] If the file format is invalid
|
31
35
|
def parse(file, encoding="ISO-8859-1")
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
|
37
|
+
path = Pathname.new(file)
|
38
|
+
load(path, encoding)
|
39
|
+
raise Fdc::FileReadError, "Invalid file extension: #{path.to_s}" unless path.extname == ".igc"
|
40
|
+
@parser.parse @file
|
35
41
|
|
36
42
|
end
|
37
43
|
|
@@ -44,133 +50,11 @@ class Fdc::Converter
|
|
44
50
|
def compile(clamp=false, extrude=false, gps=false)
|
45
51
|
|
46
52
|
# State assertion
|
47
|
-
raise RuntimeError, "Cannot compile
|
48
|
-
|
49
|
-
# Build HTML for balloon description
|
50
|
-
html = Builder::XmlMarkup.new(:indent => 2)
|
51
|
-
html.div :style => "width: 250;" do
|
52
|
-
html.p do
|
53
|
-
unless @a_records[3].nil? then
|
54
|
-
html.strong "Device:"
|
55
|
-
html.dfn @a_records[3].strip
|
56
|
-
html.br
|
57
|
-
end
|
58
|
-
end
|
59
|
-
html.p do
|
60
|
-
@h_records.each do |h|
|
61
|
-
if h.include? "PLT" and not h[2].strip.empty? then
|
62
|
-
html.strong "Pilot:"
|
63
|
-
html.dfn h[2].strip
|
64
|
-
html.br
|
65
|
-
end
|
66
|
-
if h.include? "CID" and not h[2].strip.empty? then
|
67
|
-
html.strong "Competition ID:"
|
68
|
-
html.dfn h[2].strip
|
69
|
-
html.br
|
70
|
-
end
|
71
|
-
if h.include? "GTY" and not h[2].strip.empty? then
|
72
|
-
html.strong "Glider:"
|
73
|
-
html.dfn h[2].strip
|
74
|
-
html.br
|
75
|
-
end
|
76
|
-
if h.include? "GID" and not h[2].strip.empty? then
|
77
|
-
html.strong "Glider ID:"
|
78
|
-
html.dfn h[2].strip
|
79
|
-
html.br
|
80
|
-
end
|
81
|
-
if h.include? "CCL" and not h[2].strip.empty? then
|
82
|
-
html.strong "Competition class:"
|
83
|
-
html.dfn h[2].strip
|
84
|
-
html.br
|
85
|
-
end
|
86
|
-
if h.include? "SIT" and not h[2].strip.empty? then
|
87
|
-
html.strong "Site:"
|
88
|
-
html.dfn h[2].strip
|
89
|
-
html.br
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
html.strong "Date:"
|
94
|
-
html.dfn @date[3..5].join(".")
|
95
|
-
html.br
|
96
|
-
end
|
53
|
+
raise RuntimeError, "Cannot compile without preceding parse" unless @parser.ready?
|
97
54
|
|
98
|
-
|
99
|
-
|
100
|
-
when "XSX"
|
101
|
-
@l_records.each do |l|
|
102
|
-
if matches = l[1].scan(/(\w*):(-?\d+.?\d+)/) then
|
103
|
-
html.p do
|
104
|
-
matches.each do |match|
|
105
|
-
case match[0]
|
106
|
-
when "MC"
|
107
|
-
html.strong "Max. climb:"
|
108
|
-
html.dfn match[1] << " m/s"
|
109
|
-
html.br
|
110
|
-
when "MS"
|
111
|
-
html.strong "Max. sink:"
|
112
|
-
html.dfn match[1] << " m/s"
|
113
|
-
html.br
|
114
|
-
when "MSP"
|
115
|
-
html.strong "Max. speed:"
|
116
|
-
html.dfn match[1] << " km/h"
|
117
|
-
html.br
|
118
|
-
when "Dist"
|
119
|
-
html.strong "Track distance:"
|
120
|
-
html.dfn match[1] << " km"
|
121
|
-
html.br
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
# Build KML
|
132
|
-
xml = Builder::XmlMarkup.new(:indent => 2)
|
133
|
-
xml.instruct!
|
134
|
-
xml.kml "xmlns" => "http://www.opengis.net/kml/2.2", "xmlns:gx" => "http://www.google.com/kml/ext/2.2" do
|
135
|
-
xml.Placemark {
|
136
|
-
xml.name @path.basename(@path.extname)
|
137
|
-
xml.Snippet :maxLines => "2" do
|
138
|
-
xml.text! snippet
|
139
|
-
end
|
140
|
-
xml.description do
|
141
|
-
xml.cdata! html.target!
|
142
|
-
end
|
143
|
-
xml.Style do
|
144
|
-
xml.IconStyle do
|
145
|
-
xml.Icon do
|
146
|
-
xml.href "http://earth.google.com/images/kml-icons/track-directional/track-0.png"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
xml.LineStyle do
|
150
|
-
xml.color "99ffac59"
|
151
|
-
xml.width "4"
|
152
|
-
end
|
153
|
-
end
|
154
|
-
xml.gx:Track do
|
155
|
-
|
156
|
-
clamp ? xml.altitudeMode("clampToGround") : xml.altitudeMode("absolute")
|
157
|
-
extrude ? xml.extrude("1") : xml.extrude("0")
|
158
|
-
|
159
|
-
@b_records.each do |b_record|
|
160
|
-
time = DateTime.new(2000 + @date[5].to_i, @date[4].to_i, @date[3].to_i,
|
161
|
-
b_record[1].to_i, b_record[2].to_i, b_record[3].to_i)
|
162
|
-
xml.when time
|
163
|
-
end
|
164
|
-
@b_records.each do |b_record|
|
165
|
-
coords = Fdc::GeoLocation.to_dec(b_record[5], b_record[4])
|
166
|
-
gps ? coords << b_record[8].to_f : coords << b_record[7].to_f
|
167
|
-
xml.gx :coord, coords.join(" ")
|
168
|
-
end
|
169
|
-
end
|
170
|
-
}
|
171
|
-
end
|
55
|
+
name = @path.basename(@path.extname)
|
56
|
+
@compiler.compile name, clamp, extrude, gps
|
172
57
|
|
173
|
-
@kml = xml.target!
|
174
58
|
end
|
175
59
|
|
176
60
|
# Export the compiled KML document
|
@@ -183,77 +67,17 @@ class Fdc::Converter
|
|
183
67
|
def export(dir = nil)
|
184
68
|
|
185
69
|
# Assert state
|
186
|
-
raise RuntimeError, "Cannot export before compile was called" unless @kml
|
70
|
+
raise RuntimeError, "Cannot export before compile was called" unless @compiler.kml
|
187
71
|
|
188
72
|
dir = @path.dirname.to_s unless dir
|
189
|
-
|
190
|
-
# Create Pathname for easier handling
|
191
|
-
dest = Pathname.new(dir)
|
192
|
-
|
193
|
-
# Create output file name
|
194
|
-
dest += @path.basename(@path.extname)
|
195
|
-
|
196
|
-
begin
|
197
|
-
file = File.new("#{dest.to_s}.kml", "w:UTF-8")
|
198
|
-
rescue Errno::EACCES => e
|
199
|
-
raise Fdc::FileWriteError, "Destination is write-protected: #{dir.to_s}"
|
200
|
-
rescue Errno::ENOTDIR => e
|
201
|
-
raise Fdc::FileWriteError, "Destination is not a directory: #{dir.to_s}"
|
202
|
-
rescue Errno::ENOENT => e
|
203
|
-
raise Fdc::FileWriteError, "Destination does not exist: #{dir.to_s}"
|
204
|
-
end
|
205
|
-
|
206
|
-
file.write(@kml)
|
207
|
-
file.close
|
73
|
+
write Pathname.new(dir) + (@path.basename(@path.extname).to_s << ".kml"), @compiler.kml
|
208
74
|
|
209
75
|
end
|
210
|
-
|
211
|
-
private
|
212
|
-
|
213
|
-
# Regular expressions for file parsing
|
214
|
-
REGEX_A = /^[a]([a-z\d]{3})([a-z\d]{3})?(.*)$/i
|
215
|
-
REGEX_H = /^[h][f|o|p]([\w]{3})(.*):(.*)$/i
|
216
|
-
REGEX_H_DTE = /^hf(dte)((\d{2})(\d{2})(\d{2}))/i
|
217
|
-
REGEX_B = /^(B)(\d{2})(\d{2})(\d{2})(\d{7}[NS])(\d{8}[EW])([AV])(\d{5})(\d{5})/
|
218
|
-
REGEX_L = /^l([a-z0-9]{3}|[plt]|[pfc])(.*)/i
|
219
|
-
|
220
|
-
# Parse igc file content
|
221
|
-
def parse_file
|
222
|
-
|
223
|
-
begin
|
224
|
-
|
225
|
-
# parse utc date
|
226
|
-
@date = @file.match(REGEX_H_DTE)
|
227
|
-
raise Fdc::FileFormatError, "Invalid file format - header date is missing: #{@path.to_s}" unless @date
|
228
|
-
|
229
|
-
# parse a records
|
230
|
-
@a_records = @file.match(REGEX_A)
|
231
|
-
raise Fdc::FileFormatError, "Invalid file format: #{@path.to_s}" unless @a_records
|
232
76
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
@b_records = @file.scan(REGEX_B)
|
238
|
-
|
239
|
-
# parse l records
|
240
|
-
@l_records = @file.scan(REGEX_L)
|
241
|
-
|
242
|
-
rescue ArgumentError => e
|
243
|
-
raise Fdc::FileFormatError, "Wrong file encoding: #{e.message}"
|
244
|
-
end
|
245
|
-
|
246
|
-
end
|
247
|
-
|
248
|
-
# Generate Snippet tag content
|
249
|
-
def snippet
|
250
|
-
summary = "Flight"
|
251
|
-
@h_records.each do |h|
|
252
|
-
if h.include? "SIT" and not h[2].strip.empty? then
|
253
|
-
summary << " from #{h[2].strip}"
|
254
|
-
end
|
255
|
-
end
|
256
|
-
summary << " on #{@date[3..5].join(".")}"
|
77
|
+
# Get the compiled KML document
|
78
|
+
# @return [String] The compiled KML document
|
79
|
+
def kml
|
80
|
+
@compiler.kml
|
257
81
|
end
|
258
82
|
|
259
83
|
end
|
data/lib/fdc/parser.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Parse record types from IGC file data
|
2
|
+
class Fdc::Parser
|
3
|
+
|
4
|
+
attr_reader :date_record
|
5
|
+
attr_reader :a_record
|
6
|
+
attr_reader :h_records
|
7
|
+
attr_reader :b_records
|
8
|
+
attr_reader :l_records
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@ready = false
|
12
|
+
end
|
13
|
+
|
14
|
+
# Parse the supplied IGC file content
|
15
|
+
#
|
16
|
+
# @param [String] igc_file The IGC file content
|
17
|
+
# @raise [Fdc::FileFormatError] If the file format is invalid
|
18
|
+
def parse(igc_file)
|
19
|
+
|
20
|
+
begin
|
21
|
+
# parse utc date
|
22
|
+
unless @date_record = igc_file.match(REGEX_H_DTE) then
|
23
|
+
@ready = false
|
24
|
+
raise Fdc::FileFormatError, "Invalid file format - header date is missing"
|
25
|
+
end
|
26
|
+
|
27
|
+
# parse a records
|
28
|
+
unless @a_record = igc_file.match(REGEX_A) then
|
29
|
+
@ready = false
|
30
|
+
raise Fdc::FileFormatError, "Invalid file format" unless @a_record
|
31
|
+
end
|
32
|
+
|
33
|
+
# parse h records
|
34
|
+
@h_records = igc_file.scan(REGEX_H)
|
35
|
+
|
36
|
+
# parse b records
|
37
|
+
@b_records = igc_file.scan(REGEX_B)
|
38
|
+
|
39
|
+
# parse l records
|
40
|
+
@l_records = igc_file.scan(REGEX_L)
|
41
|
+
|
42
|
+
rescue ArgumentError => e
|
43
|
+
@ready = false
|
44
|
+
raise Fdc::FileFormatError, "Wrong file encoding: #{e.message}"
|
45
|
+
end
|
46
|
+
|
47
|
+
@ready = true
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Boolean] true if {#parse} was successfully called
|
52
|
+
def ready?
|
53
|
+
return @ready
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Regular expressions for parsing igc records
|
59
|
+
REGEX_A = /^[a]([a-z\d]{3})([a-z\d]{3})?(.*)$/i
|
60
|
+
REGEX_H = /^[h][f|o|p]([\w]{3})(.*):(.*)$/i
|
61
|
+
REGEX_H_DTE = /^hf(dte)((\d{2})(\d{2})(\d{2}))/i
|
62
|
+
REGEX_B = /^(B)(\d{2})(\d{2})(\d{2})(\d{7}[NS])(\d{8}[EW])([AV])(\d{5})(\d{5})/
|
63
|
+
REGEX_L = /^l([a-z0-9]{3}|[plt]|[pfc])(.*)/i
|
64
|
+
|
65
|
+
end
|
data/lib/fdc/utilities.rb
CHANGED
@@ -32,7 +32,7 @@ module Fdc
|
|
32
32
|
|
33
33
|
end
|
34
34
|
|
35
|
-
#
|
35
|
+
# Common file loading operations
|
36
36
|
module FileLoader
|
37
37
|
|
38
38
|
# Loaded file content
|
@@ -48,32 +48,51 @@ module Fdc
|
|
48
48
|
|
49
49
|
# Load a file from the supplied path
|
50
50
|
#
|
51
|
-
# @param [
|
51
|
+
# @param [Pathname] path The path to the file
|
52
52
|
# @param [String] encoding The encoding of the file
|
53
53
|
# @raise [Fdc::FileReadError] If file could not be loaded
|
54
|
-
def load(
|
54
|
+
def load(path, encoding)
|
55
55
|
|
56
|
-
|
57
|
-
@path = Pathname.new(file)
|
58
|
-
|
59
|
-
# The file encoding
|
56
|
+
@path = path
|
60
57
|
@encoding = encoding
|
61
|
-
|
62
|
-
raise Fdc::FileReadError, "Invalid file extension: #{@path.to_s}" unless @path.extname == ".igc"
|
63
58
|
|
64
|
-
# Load file
|
65
59
|
begin
|
66
60
|
f = File.new(@path, "r", :encoding => @encoding)
|
61
|
+
@file = f.read
|
67
62
|
rescue Errno::EISDIR => e
|
68
63
|
raise Fdc::FileReadError, "Input file is a directory: #{@path.to_s}"
|
69
64
|
rescue Errno::ENOENT => e
|
70
65
|
raise Fdc::FileReadError, "Input file does not exist: #{@path.to_s}"
|
66
|
+
ensure
|
67
|
+
if f then f.close end
|
71
68
|
end
|
72
|
-
# The loaded file
|
73
|
-
@file = f.read
|
74
|
-
f.close
|
75
69
|
end
|
76
70
|
|
77
71
|
end
|
72
|
+
|
73
|
+
# Common file writing operations
|
74
|
+
module FileWriter
|
75
|
+
|
76
|
+
private
|
77
|
+
# Write a file to the file system
|
78
|
+
#
|
79
|
+
# @param [Pathname] path The path for the file
|
80
|
+
# @param [String] data The data of the file
|
81
|
+
# @raise [Fdc::FileWriteError] If dirname is not a directory or write protected
|
82
|
+
def write(path, data)
|
83
|
+
begin
|
84
|
+
file = File.new(path, "w:UTF-8")
|
85
|
+
file.write(data)
|
86
|
+
rescue Errno::EACCES => e
|
87
|
+
raise Fdc::FileWriteError, "Destination is write-protected: #{path.to_s}"
|
88
|
+
rescue Errno::ENOTDIR => e
|
89
|
+
raise Fdc::FileWriteError, "Destination is not a directory: #{path.to_s}"
|
90
|
+
rescue Errno::ENOENT => e
|
91
|
+
raise Fdc::FileWriteError, "Destination does not exist: #{path.to_s}"
|
92
|
+
ensure
|
93
|
+
if file then file.close end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
78
97
|
|
79
98
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fdc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -51,8 +51,10 @@ executables:
|
|
51
51
|
extensions: []
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
|
+
- lib/fdc/compiler.rb
|
54
55
|
- lib/fdc/converter.rb
|
55
56
|
- lib/fdc/exceptions.rb
|
57
|
+
- lib/fdc/parser.rb
|
56
58
|
- lib/fdc/utilities.rb
|
57
59
|
- lib/fdc.rb
|
58
60
|
- bin/fdc
|