dost 0.0.2

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/dost.rb +105 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: '07449a34d8548c23ddc740498a7b25bf3d06b708'
4
+ data.tar.gz: 9b7fed4703a1f1137aee3e7d27df27de56834a91
5
+ SHA512:
6
+ metadata.gz: 6a632d921c55c5e6ebb4f30ee689f8ecb84f1c1a3d782ef7e21110f8491b15979afcbc59953c345a2f5039b5c0617ba148d498caffe60870838ffbfb44c8934b
7
+ data.tar.gz: 331c93a7d4ab90f9bc07a32fd0f16f1890b9efd6acfa518c3aa48909c14f34b1fa0a09b7f8b83f650ee69943b830e475e40b49a96247882cdef44e43edf9f422
data/lib/dost.rb ADDED
@@ -0,0 +1,105 @@
1
+ module DOST
2
+ class Data
3
+ attr_reader :lines, :headers_delimiters, :values_delimiters
4
+
5
+ def initialize(lines:, headers_delimiters:, values_delimiters:)
6
+ @lines = lines.map(&:chomp)
7
+ @headers_delimiters = headers_delimiters
8
+ @values_delimiters = values_delimiters
9
+ end
10
+
11
+ def headers
12
+ @headers ||= parse_headers
13
+ end
14
+
15
+ def values
16
+ @values ||= parse_values
17
+ end
18
+
19
+ private def parse_headers
20
+ raw_headers = header_lines.map { |header_line| calc_ranges(header_line) }
21
+
22
+ first_row = raw_headers.first
23
+ second_row = raw_headers.last
24
+
25
+ first_row.map do |(first_key, first_range)|
26
+ values_inside = second_row.select do |(lk, lr)|
27
+ overlaps?((lr.first..(lk.length + lr.first)), (first_range.first..(first_range.first + first_key.length)))
28
+ end
29
+
30
+ if !values_inside.empty? && values_inside.count > 1
31
+ values_inside.map.with_index do |(second_item_key, second_item_range), index|
32
+ key = (first_key.to_s + second_item_key.to_s.prepend('_')).to_sym
33
+ is_last_item = (index == values_inside.count - 1)
34
+ left_bound = index.zero? ? [second_item_range.first, first_range.first].min : second_item_range.first
35
+ right_bound = is_last_item ? [second_item_range.last, first_range.last].min : second_item_range.last
36
+
37
+ range = left_bound..right_bound
38
+ [key, range]
39
+ end
40
+ else
41
+ [[first_key, first_range]]
42
+ end
43
+ end.flatten(1)
44
+ end
45
+
46
+ private def parse_values
47
+ values_lines.map do |line|
48
+ headers.map do |(name, range)|
49
+ [name, line[range].strip]
50
+ end.to_h
51
+ end
52
+ end
53
+
54
+ private def calc_ranges(header_line)
55
+ header_line.split(%r{(^\s*\S*\s*)|(\S*\s*)}).reject(&:empty?).reduce([]) do |acc, key|
56
+ index = acc.last&.last&.last || -1;
57
+ acc.push([key.strip.downcase.to_sym, (index + 1)..(index + (key.length))])
58
+ end
59
+ end
60
+
61
+ private def values_lines
62
+ lines_between_delimiters(values_delimiters.first, values_delimiters.last)
63
+ end
64
+
65
+ private def header_lines
66
+ lines_between_delimiters(headers_delimiters.first, headers_delimiters.last)
67
+ end
68
+
69
+ private def lines_between_delimiters(delimiter_start, delimiter_end)
70
+ lines.reduce([]) do |acc, line|
71
+ if acc.empty?
72
+ acc.push(line) if delimiter?(line) && delimiter_char(line) == delimiter_start
73
+ else
74
+ if delimiter?(line)
75
+ if delimiter_char(line) == delimiter_end
76
+ return acc[1..-1]
77
+ else
78
+ acc = [line]
79
+ end
80
+ else
81
+ acc.push(line)
82
+ end
83
+ end
84
+ acc
85
+ end
86
+ end
87
+
88
+ private def delimiter?(line)
89
+ line.chars.uniq.count == 1 && !blank?(delimiter_char(line))
90
+ end
91
+
92
+ private def delimiter_char(line)
93
+ line.chars.uniq.first
94
+ end
95
+
96
+ private def blank?(str)
97
+ str !~ /[^[:space:]]/
98
+ end
99
+
100
+ # from https://apidock.com/rails/Range/overlaps
101
+ private def overlaps?(orig, other)
102
+ orig.cover?(other.first) || other.cover?(orig.first)
103
+ end
104
+ end
105
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dost
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Ivan Takarlikov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple gem to parse Dynamic Offset Separated files
14
+ email: vtakarlikov@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/dost.rb
20
+ homepage: https://rubygems.org/gems/dost
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.6.14.4
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Parse DOST files easy
44
+ test_files: []