property-list 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rdoc_options +23 -0
- data/README.md +21 -11
- data/lib/property-list.rb +13 -15
- data/lib/property-list/ascii_generator.rb +40 -20
- data/lib/property-list/ascii_parser.rb +4 -3
- data/lib/property-list/binary_generator.rb +2 -1
- data/lib/property-list/binary_markers.rb +1 -1
- data/lib/property-list/binary_parser.rb +3 -2
- data/lib/property-list/version.rb +1 -1
- data/lib/property-list/xml_generator.rb +28 -18
- data/lib/property-list/xml_parser.rb +2 -1
- data/property-list.gemspec +4 -2
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a77c93353f4ae1b3e24f38e0976a133a68251ec
|
4
|
+
data.tar.gz: 2c68650d8755fc85dd1752951e930f153624a372
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 786bb0eaba6ebf83dee461f951ce9966b51c649e945fd1a06ebb3d6a7176ebd886abb6c773172ae85455a310a23a9b93ed00b567b18d58b5bc74cc4696985e4d
|
7
|
+
data.tar.gz: 4c64f96962192fa6cea63ceb476baaa9129996ec33f322465134b169b19b270ff136836419ca18ddd96fe5a804a35948fa89bdb6c0f8dc89dc4cc8fee4f10ed4
|
data/.rdoc_options
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
--- !ruby/object:RDoc::Options
|
2
|
+
encoding: UTF-8
|
3
|
+
static_path: []
|
4
|
+
rdoc_include:
|
5
|
+
- "."
|
6
|
+
charset: UTF-8
|
7
|
+
exclude:
|
8
|
+
- "test"
|
9
|
+
hyperlink_all: false
|
10
|
+
line_numbers: false
|
11
|
+
locale:
|
12
|
+
locale_dir: locale
|
13
|
+
locale_name:
|
14
|
+
main_page:
|
15
|
+
markup: markdown
|
16
|
+
output_decoration: true
|
17
|
+
page_dir:
|
18
|
+
show_hash: false
|
19
|
+
tab_width: 8
|
20
|
+
template_stylesheets: []
|
21
|
+
title:
|
22
|
+
visibility: :protected
|
23
|
+
webcvs:
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
Fully featured propertylist library.
|
2
|
+
Can load and dump XML/ASCII/Binary plists and offer fine-grained formatting options.
|
3
|
+
Cross platform, clean code, performance tuned, no dependency.
|
4
4
|
|
5
5
|
## Install
|
6
6
|
|
@@ -25,20 +25,22 @@ Generate a plist file data
|
|
25
25
|
|
26
26
|
XML formatting options for `PropertyList.dump_xml object, options`
|
27
27
|
|
28
|
-
- `segment:` whether
|
28
|
+
- `segment:` whether output an XML segment (not wrapped with `<?xml>`, `<DOCTYPE>`, `<plist>` tags), default is `false`.
|
29
29
|
- `xml_version:` you can also specify `"1.1"` for https://www.w3.org/TR/xml11/, default is `"1.0"`, no effect if `:segment` is set to `true`.
|
30
|
-
- `
|
30
|
+
- `gnu_dtd:` use GNUStep DTD instead (which is a bit different in string escaping), default is `false`.
|
31
|
+
- `indent_unit:` the indent unit, default value is `"\t"`, set to or `''` if you don't need indent.
|
31
32
|
- `initial_indent:` initial indent space, default is `''`, the indentation per line equals to `initial_indent + indent * current_indent_level`.
|
32
33
|
- `base64_width:` the width of characters per line when serializing data with Base64, default value is `68`, must be multiple of `4`.
|
33
34
|
- `base64_indent:` whether indent the Base64 encoded data, you can use `false` for compatibility to generate same output for other frameworks, default value is `true`.
|
34
35
|
|
35
36
|
ASCII formatting options for `PropertyList.dump_ascii object, options`
|
36
37
|
|
37
|
-
- `indent_unit:` the indent unit, default value is `"\t"`, set to `''` if you don't need indent
|
38
|
-
- `initial_indent:` initial indent space, default is `''`, the indentation per line equals to `initial_indent + indent * current_indent_level
|
38
|
+
- `indent_unit:` the indent unit, default value is `"\t"`, set to `''` if you don't need indent.
|
39
|
+
- `initial_indent:` initial indent space, default is `''`, the indentation per line equals to `initial_indent + indent * current_indent_level`.
|
39
40
|
- `wrap:` wrap the top level output with `{...}` when obj is a Hash, default is `true`.
|
40
|
-
- `encoding_comment:` add encoding comment `// !$*UTF8*$!` on top of file, default is `false
|
41
|
-
- `sort_keys:` sort dict keys, default is `true
|
41
|
+
- `encoding_comment:` add encoding comment `// !$*UTF8*$!` on top of file, default is `false`.
|
42
|
+
- `sort_keys:` sort dict keys, default is `true`.
|
43
|
+
- `gnu_extension` whether allow GNUStep extensions for ASCII plist to support serializing more types, default is `true`.
|
42
44
|
|
43
45
|
## Data type mapping
|
44
46
|
|
@@ -51,7 +53,10 @@ Data type mapping in `PropertyList.load`:
|
|
51
53
|
date: DateTime
|
52
54
|
true: true
|
53
55
|
false: false
|
54
|
-
uid: PropertyList::
|
56
|
+
uid: PropertyList::UID # only in binary plist, obj.uid is the integer index
|
57
|
+
array: Array
|
58
|
+
dict: Hash
|
59
|
+
set: Set # only in binary plist
|
55
60
|
|
56
61
|
Reverse mapping in `PropertyList.dump_*`:
|
57
62
|
|
@@ -62,7 +67,12 @@ Reverse mapping in `PropertyList.dump_*`:
|
|
62
67
|
Time, DateTime, Date: date
|
63
68
|
true: true
|
64
69
|
false: false
|
65
|
-
PropertyList::Uid: uid
|
70
|
+
PropertyList::Uid: uid # only in binary plist
|
71
|
+
Dict: dict
|
72
|
+
Array: array
|
73
|
+
Set: set # only in binary plist
|
74
|
+
|
75
|
+
Type mappings in ASCII plist depends on the DTD.
|
66
76
|
|
67
77
|
## Credits
|
68
78
|
|
data/lib/property-list.rb
CHANGED
@@ -14,22 +14,17 @@ require_relative 'property-list/binary_generator'
|
|
14
14
|
require_relative 'property-list/binary_parser'
|
15
15
|
require_relative 'property-list/version'
|
16
16
|
|
17
|
-
# === Load a plist file
|
18
|
-
#
|
19
|
-
# PropertyList.load_xml File.read "some_plist.xml"
|
20
|
-
# PropertyList.load_binary File.binread "some_binary.plist"
|
21
|
-
# PropertyList.load_ascii File.read "some_ascii.strings"
|
22
|
-
# PropertyList.load File.binread "unknown_format.plist"
|
23
|
-
#
|
24
|
-
# === Generate a plist file data
|
25
|
-
#
|
26
|
-
# PropertyList.dump_xml obj
|
27
|
-
# PropertyList.dump_binary obj
|
28
|
-
# PropertyList.dump_ascii obj
|
29
|
-
#
|
30
17
|
module PropertyList
|
31
|
-
#
|
32
|
-
#
|
18
|
+
# Load plist from file
|
19
|
+
#
|
20
|
+
# Auto detects format
|
21
|
+
def self.load_file file_name
|
22
|
+
load File.binread file_name
|
23
|
+
end
|
24
|
+
|
25
|
+
# Load plist (binary or xml or ascii) into a ruby object.
|
26
|
+
#
|
27
|
+
# Auto detects format.
|
33
28
|
def self.load data
|
34
29
|
case data.byteslice(0, 8)
|
35
30
|
when /\Abplist\d\d/n
|
@@ -44,6 +39,9 @@ module PropertyList
|
|
44
39
|
class SyntaxError < RuntimeError
|
45
40
|
end
|
46
41
|
|
42
|
+
class UnsupportedTypeError < RuntimeError
|
43
|
+
end
|
44
|
+
|
47
45
|
# binary plist v0x elements:
|
48
46
|
|
49
47
|
class UID
|
@@ -1,18 +1,17 @@
|
|
1
1
|
module PropertyList
|
2
|
-
#
|
2
|
+
# Generate ASCII (Plain) plist.
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# Options:
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# - `indent_unit:` the indent unit, default value is `"\t"`, set to `''` if you don't need indent.
|
7
|
+
# - `initial_indent:` initial indent space, default is `''`, the indentation per line equals to `initial_indent + indent * current_indent_level`.
|
8
|
+
# - `wrap:` wrap the top level output with `{...}` when obj is a Hash, default is `true`.
|
9
|
+
# - `encoding_comment:` add encoding comment `// !$*UTF8*$!` on top of file, default is `false`.
|
10
|
+
# - `sort_keys:` sort dict keys, default is `true`.
|
11
|
+
# - `gnu_extension` whether allow GNUStep extensions for ASCII plist to support serializing more types, default is `true`.
|
7
12
|
#
|
8
|
-
|
9
|
-
|
10
|
-
# [:encoding_comment] add encoding comment '!$*UTF8*$!' on top of file, default is false
|
11
|
-
#
|
12
|
-
# [:sort_keys] sort dict keys, default is true
|
13
|
-
#
|
14
|
-
def self.dump_ascii obj, indent_unit: "\t", initial_indent: '', wrap: true, encoding_comment: false, sort_keys: true
|
15
|
-
generator = AsciiGenerator.new indent_unit: indent_unit, initial_indent: initial_indent, sort_keys: sort_keys
|
13
|
+
def self.dump_ascii obj, indent_unit: "\t", initial_indent: '', wrap: true, encoding_comment: false, sort_keys: true, gnu_extension: true
|
14
|
+
generator = AsciiGenerator.new indent_unit: indent_unit, initial_indent: initial_indent, sort_keys: sort_keys, gnu_extension: gnu_extension
|
16
15
|
generator.output << "// !$*UTF8*$!\n" if encoding_comment
|
17
16
|
generator.generate obj, wrap
|
18
17
|
generator.output << "\n" if wrap and obj.is_a?(Hash)
|
@@ -20,12 +19,13 @@ module PropertyList
|
|
20
19
|
end
|
21
20
|
|
22
21
|
class AsciiGenerator #:nodoc:
|
23
|
-
def initialize indent_unit: "\t", initial_indent: '', sort_keys: true
|
22
|
+
def initialize indent_unit: "\t", initial_indent: '', sort_keys: true, gnu_extension: true
|
24
23
|
@indent_unit = indent_unit
|
25
24
|
@indent_level = 0
|
26
25
|
@initial_indent = initial_indent
|
27
26
|
@indent = @initial_indent + @indent_unit * @indent_level
|
28
27
|
@sort_keys = sort_keys
|
28
|
+
@gnu_extension = gnu_extension
|
29
29
|
@output = []
|
30
30
|
end
|
31
31
|
attr_reader :output
|
@@ -52,18 +52,38 @@ module PropertyList
|
|
52
52
|
ascii_hash_content object
|
53
53
|
end
|
54
54
|
when true
|
55
|
-
|
55
|
+
if @gnu_extension
|
56
|
+
ascii_value "<*BY>"
|
57
|
+
else
|
58
|
+
raise UnsupportedTypeError, 'TrueClass'
|
59
|
+
end
|
56
60
|
when false
|
57
|
-
|
61
|
+
if @gnu_extension
|
62
|
+
ascii_value "<*BN>"
|
63
|
+
else
|
64
|
+
raise UnsupportedTypeError, 'FalseClass'
|
65
|
+
end
|
58
66
|
when Float
|
59
|
-
if
|
60
|
-
object
|
67
|
+
if @gnu_extension
|
68
|
+
if object.to_i == object
|
69
|
+
object = object.to_i
|
70
|
+
end
|
71
|
+
ascii_value "<*R#{object}>"
|
72
|
+
else
|
73
|
+
raise UnsupportedTypeError, 'Float'
|
61
74
|
end
|
62
|
-
ascii_value "<*R#{object}>"
|
63
75
|
when Integer
|
64
|
-
|
76
|
+
if @gnu_extension
|
77
|
+
ascii_value "<*I#{object}>"
|
78
|
+
else
|
79
|
+
raise UnsupportedTypeError, 'Integer'
|
80
|
+
end
|
65
81
|
when Time, Date # also covers DateTime
|
66
|
-
|
82
|
+
if @gnu_extension
|
83
|
+
ascii_value "<*D#{object.strftime '%Y-%m-%d %H:%M:%S %z'}>"
|
84
|
+
else
|
85
|
+
raise UnsupportedTypeError, object.class.to_s
|
86
|
+
end
|
67
87
|
when String
|
68
88
|
ascii_string object
|
69
89
|
when Symbol
|
@@ -73,7 +93,7 @@ module PropertyList
|
|
73
93
|
contents = object.read
|
74
94
|
ascii_data contents
|
75
95
|
else
|
76
|
-
raise
|
96
|
+
raise UnsupportedTypeError, object.class.to_s
|
77
97
|
end
|
78
98
|
end
|
79
99
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module PropertyList
|
2
|
-
|
3
|
-
|
2
|
+
# Parse ASCII plist into a Ruby object
|
3
|
+
def self.load_ascii text
|
4
|
+
AsciiParser.new(text).parse
|
4
5
|
end
|
5
6
|
|
6
|
-
class AsciiParser
|
7
|
+
class AsciiParser #:nodoc:
|
7
8
|
def initialize src
|
8
9
|
@lexer = StringScanner.new src.strip
|
9
10
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
|
3
3
|
module PropertyList
|
4
|
+
# Generate binary plist, the version is auto detected
|
4
5
|
def self.dump_binary obj, options=nil
|
5
6
|
generator = BinaryGenerator.new options
|
6
7
|
generator.generate obj
|
@@ -11,7 +12,7 @@ module PropertyList
|
|
11
12
|
# https://github.com/jarib/plist/blob/master/lib/plist/binary.rb
|
12
13
|
#
|
13
14
|
# With improved performance
|
14
|
-
class BinaryGenerator
|
15
|
+
class BinaryGenerator #:nodoc:
|
15
16
|
include BinaryMarkers
|
16
17
|
|
17
18
|
def initialize opts
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module PropertyList
|
2
|
-
|
2
|
+
# Parse binary plist into a Ruby object
|
3
|
+
def self.load_binary data
|
3
4
|
BinaryParser.new(data).parse
|
4
5
|
end
|
5
6
|
|
6
7
|
# Reference:
|
7
8
|
# https://opensource.apple.com/source/CF/CF-1151.16/CFBinaryPList.c.auto.html
|
8
|
-
class BinaryParser
|
9
|
+
class BinaryParser #:nodoc:
|
9
10
|
include BinaryMarkers
|
10
11
|
|
11
12
|
def initialize src
|
@@ -1,31 +1,34 @@
|
|
1
1
|
module PropertyList
|
2
2
|
|
3
|
-
#
|
3
|
+
# Generate ASCII (Plain) plist.
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Options:
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# - `segment:` whether output an XML segment (not wrapped with `<?xml>`, `<DOCTYPE>`, `<plist>` tags), default is `false`.
|
8
|
+
# - `xml_version:` you can also specify `"1.1"` for https://www.w3.org/TR/xml11/, default is `"1.0"`, no effect if `:segment` is set to `true`.
|
9
|
+
# - `gnu_dtd:` use GNUStep DTD instead (which is a bit different in string escaping), default is `false`.
|
10
|
+
# - `indent_unit:` the indent unit, default value is `"\t"`, set to or `''` if you don't need indent.
|
11
|
+
# - `initial_indent:` initial indent space, default is `''`, the indentation per line equals to `initial_indent + indent * current_indent_level`.
|
12
|
+
# - `base64_width:` the width of characters per line when serializing data with Base64, default value is `68`, must be multiple of `4`.
|
13
|
+
# - `base64_indent:` whether indent the Base64 encoded data, you can use `false` for compatibility to generate same output for other frameworks, default value is `true`.
|
8
14
|
#
|
9
|
-
|
10
|
-
#
|
11
|
-
# [:initial_indent] initial indent space, default is <code>''</code>, the indentation per line equals to <code>initial_indent + indent * current_indent_level</code>
|
12
|
-
#
|
13
|
-
# [:base64_width] the width of characters per line when serializing data with Base64, default value is <code>68</code>, must be multiple of <code>4</code>
|
14
|
-
#
|
15
|
-
# [:base64_indent] whether indent the Base64 encoded data, you can use <code>false</code> for compatibility to generate same output for other frameworks, default value is <code>true</code>
|
16
|
-
#
|
17
|
-
def self.dump_xml obj, segment: false, xml_version: '1.0', base64_width: 68, base64_indent: true, indent_unit: "\t", initial_indent: ''
|
15
|
+
def self.dump_xml obj, segment: false, xml_version: '1.0', gnu_dtd: false, base64_width: 68, base64_indent: true, indent_unit: "\t", initial_indent: ''
|
18
16
|
if !base64_width.is_a?(Integer) or base64_width <= 0 or base64_width % 4 != 0
|
19
17
|
raise ArgumentError, "option :base64_width must be a positive integer and a multiple of 4"
|
20
18
|
end
|
21
19
|
|
22
|
-
generator = XmlGenerator.new base64_width: base64_width, base64_indent: base64_indent, indent_unit: indent_unit, initial_indent: initial_indent
|
20
|
+
generator = XmlGenerator.new gnu_dtd: gnu_dtd, base64_width: base64_width, base64_indent: base64_indent, indent_unit: indent_unit, initial_indent: initial_indent
|
23
21
|
if segment
|
24
22
|
generator.generate obj
|
25
23
|
else
|
26
24
|
generator.output << %|<?xml version="#{xml_version}" encoding="UTF-8"?>\n|
|
27
|
-
|
28
|
-
|
25
|
+
if gnu_dtd
|
26
|
+
generator.output << %|<!DOCTYPE plist PUBLIC "-//GNUstep//DTD plist 0.9//EN" "http://www.gnustep.org/plist-0_9.xml">\n|
|
27
|
+
generator.output << %|<plist>\n|
|
28
|
+
else
|
29
|
+
generator.output << %|<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n|
|
30
|
+
generator.output << %|<plist version="1.0">\n|
|
31
|
+
end
|
29
32
|
generator.generate obj
|
30
33
|
generator.output << %|</plist>\n|
|
31
34
|
end
|
@@ -33,7 +36,8 @@ module PropertyList
|
|
33
36
|
end
|
34
37
|
|
35
38
|
class XmlGenerator #:nodoc:
|
36
|
-
def initialize base64_width: 68, base64_indent: true, indent_unit: "\t", initial_indent: ''
|
39
|
+
def initialize gnu_dtd: false, base64_width: 68, base64_indent: true, indent_unit: "\t", initial_indent: ''
|
40
|
+
@gnu_dtd = gnu_dtd
|
37
41
|
@indent_unit = indent_unit
|
38
42
|
@indent_level = 0
|
39
43
|
@initial_indent = initial_indent
|
@@ -101,7 +105,7 @@ module PropertyList
|
|
101
105
|
contents = obj.read
|
102
106
|
data_tag contents
|
103
107
|
else
|
104
|
-
raise
|
108
|
+
raise UnsupportedTypeError, obj.class.to_s
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
@@ -139,9 +143,15 @@ module PropertyList
|
|
139
143
|
TABLE_FOR_ESCAPE = {"&" => "&", "<" => "<", ">" => ">"}.freeze
|
140
144
|
def escape_string s
|
141
145
|
# Likes CGI.escapeHTML but leaves `'` or `"` as mac plist does
|
142
|
-
s.gsub /[&<>]/ do |c|
|
146
|
+
s = s.gsub /[&<>]/ do |c|
|
143
147
|
TABLE_FOR_ESCAPE[c]
|
144
148
|
end
|
149
|
+
if @gnu_dtd
|
150
|
+
# use \u to escape all control chars
|
151
|
+
s.gsub(/[[:cntrl:]]/) {|c| "\\U#{c.ord.to_s(16).rjust 4, '0'}" }
|
152
|
+
else
|
153
|
+
s
|
154
|
+
end
|
145
155
|
end
|
146
156
|
end
|
147
157
|
end
|
data/property-list.gemspec
CHANGED
@@ -6,8 +6,10 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.authors = ["Luikore"]
|
7
7
|
spec.email = 'no@email'
|
8
8
|
|
9
|
-
spec.summary = "Property List (plist) library with all formats support"
|
10
|
-
spec.description = "
|
9
|
+
spec.summary = "Property List (plist, propertylist) library with all formats support"
|
10
|
+
spec.description = "Fully featured propertylist library.
|
11
|
+
Can load and dump XML/ASCII/Binary plists and offer fine-grained formatting options.
|
12
|
+
Cross platform, clean code, performance tuned, no dependency."
|
11
13
|
spec.homepage = "https://github.com/luikore/property-list"
|
12
14
|
spec.license = "BSD-3-Clause"
|
13
15
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: property-list
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luikore
|
@@ -80,15 +80,17 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.14'
|
83
|
-
description:
|
84
|
-
|
85
|
-
|
83
|
+
description: |-
|
84
|
+
Fully featured propertylist library.
|
85
|
+
Can load and dump XML/ASCII/Binary plists and offer fine-grained formatting options.
|
86
|
+
Cross platform, clean code, performance tuned, no dependency.
|
86
87
|
email: no@email
|
87
88
|
executables: []
|
88
89
|
extensions: []
|
89
90
|
extra_rdoc_files: []
|
90
91
|
files:
|
91
92
|
- ".gitignore"
|
93
|
+
- ".rdoc_options"
|
92
94
|
- LICENSE
|
93
95
|
- README.md
|
94
96
|
- Rakefile
|
@@ -127,5 +129,5 @@ rubyforge_project:
|
|
127
129
|
rubygems_version: 2.6.11
|
128
130
|
signing_key:
|
129
131
|
specification_version: 4
|
130
|
-
summary: Property List (plist) library with all formats support
|
132
|
+
summary: Property List (plist, propertylist) library with all formats support
|
131
133
|
test_files: []
|