ffi-clang 0.3.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/.rspec +4 -0
- data/.travis.yml +20 -9
- data/Gemfile +10 -1
- data/README.md +1 -1
- data/Rakefile +9 -9
- data/examples/docs.cpp +25 -0
- data/examples/docs.rb +31 -0
- data/ffi-clang.gemspec +1 -1
- data/lib/ffi/clang.rb +16 -13
- data/lib/ffi/clang/clang_version.rb +29 -0
- data/lib/ffi/clang/code_completion.rb +1 -1
- data/lib/ffi/clang/comment.rb +8 -4
- data/lib/ffi/clang/compilation_database.rb +1 -1
- data/lib/ffi/clang/cursor.rb +42 -15
- data/lib/ffi/clang/diagnostic.rb +6 -2
- data/lib/ffi/clang/file.rb +6 -9
- data/lib/ffi/clang/index.rb +4 -4
- data/lib/ffi/clang/lib.rb +1 -1
- data/lib/ffi/clang/lib/{utils.rb → clang_version.rb} +1 -1
- data/lib/ffi/clang/lib/code_completion.rb +2 -3
- data/lib/ffi/clang/lib/comment.rb +0 -2
- data/lib/ffi/clang/lib/compilation_database.rb +6 -9
- data/lib/ffi/clang/lib/cursor.rb +10 -18
- data/lib/ffi/clang/lib/diagnostic.rb +4 -4
- data/lib/ffi/clang/lib/file.rb +4 -6
- data/lib/ffi/clang/lib/inclusions.rb +2 -2
- data/lib/ffi/clang/lib/index.rb +0 -2
- data/lib/ffi/clang/lib/source_location.rb +6 -8
- data/lib/ffi/clang/lib/source_range.rb +1 -1
- data/lib/ffi/clang/lib/string.rb +0 -2
- data/lib/ffi/clang/lib/translation_unit.rb +2 -2
- data/lib/ffi/clang/lib/type.rb +8 -17
- data/lib/ffi/clang/source_location.rb +2 -2
- data/lib/ffi/clang/source_range.rb +16 -3
- data/lib/ffi/clang/token.rb +4 -4
- data/lib/ffi/clang/translation_unit.rb +5 -5
- data/lib/ffi/clang/type.rb +0 -14
- data/lib/ffi/clang/version.rb +2 -2
- data/spec/{clang → ffi/clang}/code_completion_spec.rb +6 -6
- data/spec/{clang → ffi/clang}/comment_spec.rb +22 -39
- data/spec/{clang → ffi/clang}/compilation_database_spec.rb +8 -10
- data/spec/{clang → ffi/clang}/cursor_spec.rb +89 -97
- data/spec/{clang → ffi/clang}/diagnostic_spec.rb +9 -10
- data/spec/{clang → ffi/clang}/file_spec.rb +3 -5
- data/spec/{fixtures → ffi/clang/fixtures}/a.c +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/canonical.c +0 -0
- data/spec/ffi/clang/fixtures/class.cpp +8 -0
- data/spec/{fixtures → ffi/clang/fixtures}/compile_commands.json +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/completion.cxx +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/docs.c +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/docs.cc +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/docs.h +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/list.c +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/location1.c +0 -0
- data/spec/ffi/clang/fixtures/simple.ast +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/simple.c +0 -0
- data/spec/{fixtures → ffi/clang/fixtures}/test.cxx +0 -0
- data/spec/{clang → ffi/clang}/index_spec.rb +17 -14
- data/spec/{clang → ffi/clang}/source_location_spec.rb +12 -14
- data/spec/{clang → ffi/clang}/source_range_spec.rb +12 -14
- data/spec/{clang → ffi/clang}/token_spec.rb +6 -8
- data/spec/{clang → ffi/clang}/translation_unit_spec.rb +28 -30
- data/spec/{clang → ffi/clang}/type_spec.rb +17 -33
- data/spec/ffi/clang/version_spec.rb +28 -0
- data/spec/spec_helper.rb +11 -37
- metadata +61 -55
- data/lib/ffi/clang/utils.rb +0 -89
- data/spec/clang/utils_spec.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3fba953ec692d348f92786e6892450d93011103
|
4
|
+
data.tar.gz: 4e1b34caa60d2d0a577471d419170f998e1d5451
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b90f7d9d97dca48869b045e76c3f1c57e6efc390a67c0a07cb95527a85c735f70f22cbf76e9a0745a3233fa9cc388c42efdb1ec0c042583c413335801f376132
|
7
|
+
data.tar.gz: ea69e1a70cb738ae85cbfd86a5de317724054926cdbc2e2bab50aa154497d53104ead7af30d7afb8e84c750f5e40952b2cde388b19f63621c48e2b975adb8239
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -5,15 +5,26 @@ before_install:
|
|
5
5
|
- export PATH=/usr/lib/llvm-${LLVM_VERSION}/bin:$PATH
|
6
6
|
matrix:
|
7
7
|
include:
|
8
|
-
|
9
|
-
- &libclang-36
|
10
|
-
addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-3.6], packages: [libclang-3.6-dev, clang-3.6]}}
|
8
|
+
- addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-3.6], packages: [libclang-3.6-dev, clang-3.6]}}
|
11
9
|
env: LLVM_VERSION=3.6
|
12
|
-
rvm: "2.
|
13
|
-
# A second build with the same configuration but using ruby 2.2.4
|
14
|
-
- <<: *libclang-36
|
15
|
-
rvm: "2.2.4"
|
16
|
-
# Other builds on other versions of LLVM, all using ruby 2.3.0
|
10
|
+
rvm: "2.4.0"
|
17
11
|
- addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-3.7], packages: [libclang-3.7-dev, clang-3.7]}}
|
18
12
|
env: LLVM_VERSION=3.7
|
19
|
-
rvm: "2.
|
13
|
+
rvm: "2.4.0"
|
14
|
+
# The default build:
|
15
|
+
- &libclang-38
|
16
|
+
addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-3.8], packages: [libclang-3.8-dev, clang-3.8]}}
|
17
|
+
env: LLVM_VERSION=3.8
|
18
|
+
rvm: "2.4.0"
|
19
|
+
# A second build with the same configuration but using ruby 2.2.4
|
20
|
+
- <<: *libclang-38
|
21
|
+
rvm: "2.3.3"
|
22
|
+
- addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-3.9], packages: [libclang-3.9-dev, clang-3.9]}}
|
23
|
+
env: LLVM_VERSION=3.9
|
24
|
+
rvm: "2.4.0"
|
25
|
+
- addons: {apt: {sources: [ubuntu-toolchain-r-test, llvm-toolchain-precise-4.0], packages: [libclang-4.0-dev, clang-4.0]}}
|
26
|
+
env: LLVM_VERSION=4.0
|
27
|
+
rvm: "2.4.0"
|
28
|
+
allow_failures:
|
29
|
+
- env: LLVM_VERSION=4.0
|
30
|
+
rvm: "2.4.0"
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# FFI::Clang
|
2
2
|
|
3
|
-
A light-weight wrapper for Ruby exposing [libclang][1].
|
3
|
+
A light-weight wrapper for Ruby exposing [libclang][1]. Works for libclang v3.4+.
|
4
4
|
|
5
5
|
[](http://travis-ci.org/ioquatix/ffi-clang)
|
6
6
|
[](https://codeclimate.com/github/ioquatix/ffi-clang)
|
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
task
|
7
|
-
|
8
|
-
|
9
|
-
RSpec::Core::RakeTask.new do |t|
|
10
|
-
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
11
|
-
# Put spec opts in a file named .rspec in root
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
5
|
+
begin
|
6
|
+
require('simplecov/version')
|
7
|
+
task.rspec_opts = %w{--require simplecov} if ENV['COVERAGE']
|
8
|
+
rescue LoadError
|
9
|
+
end
|
12
10
|
end
|
11
|
+
|
12
|
+
task :default => :spec
|
data/examples/docs.cpp
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
/** A test class which does nothing.
|
3
|
+
|
4
|
+
This is used by `main`.
|
5
|
+
*/
|
6
|
+
template<typename T>
|
7
|
+
class Test {};
|
8
|
+
|
9
|
+
/// This is a specialization for integers.
|
10
|
+
template<>
|
11
|
+
class Test<int> {
|
12
|
+
public:
|
13
|
+
/// The number of times it has been incremented.
|
14
|
+
int count;
|
15
|
+
|
16
|
+
};
|
17
|
+
|
18
|
+
/// This always fails.
|
19
|
+
/// @param argc The number of items in `argv`. At least 1.
|
20
|
+
/// @param argv The command line arguments, with argv[0] being the command used to execute this program.
|
21
|
+
int main(int argc, char ** argv) {
|
22
|
+
Test<int> test;
|
23
|
+
|
24
|
+
return 1;
|
25
|
+
}
|
data/examples/docs.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rainbow'
|
4
|
+
require 'ffi/clang'
|
5
|
+
|
6
|
+
index = FFI::Clang::Index.new
|
7
|
+
|
8
|
+
# clang -Xclang -ast-dump -fsyntax-only ./examples/docs.cpp
|
9
|
+
|
10
|
+
def title(declaration)
|
11
|
+
puts ["Symbol:", Rainbow(declaration.spelling).blue.bright, "Type:", Rainbow(declaration.type.spelling).green, declaration.kind.to_s].join(' ')
|
12
|
+
end
|
13
|
+
|
14
|
+
ARGV.each do |path|
|
15
|
+
translation_unit = index.parse_translation_unit(path)
|
16
|
+
|
17
|
+
declarations = translation_unit.cursor.select(&:declaration?)
|
18
|
+
|
19
|
+
declarations.each do |declaration|
|
20
|
+
title declaration
|
21
|
+
|
22
|
+
if location = declaration.location
|
23
|
+
puts "Defined at #{location.file}:#{location.line}"
|
24
|
+
end
|
25
|
+
|
26
|
+
if comment = declaration.comment
|
27
|
+
# puts Rainbow(comment.inspect).gray
|
28
|
+
puts Rainbow(comment.text)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/ffi-clang.gemspec
CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency "ffi"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.4.0"
|
25
25
|
spec.add_development_dependency "rake"
|
26
26
|
end
|
data/lib/ffi/clang.rb
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
# THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'ffi'
|
23
|
-
require
|
23
|
+
require 'rbconfig'
|
24
24
|
|
25
25
|
module FFI::Clang
|
26
26
|
class Error < StandardError
|
@@ -42,15 +42,18 @@ module FFI::Clang
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
# Load the shared object:
|
46
|
+
require_relative 'clang/lib'
|
47
|
+
|
48
|
+
# Wrappers around C functionality:
|
49
|
+
require_relative 'clang/clang_version'
|
50
|
+
require_relative 'clang/index'
|
51
|
+
require_relative 'clang/translation_unit'
|
52
|
+
require_relative 'clang/diagnostic'
|
53
|
+
require_relative 'clang/cursor'
|
54
|
+
require_relative 'clang/source_location'
|
55
|
+
require_relative 'clang/source_range'
|
56
|
+
require_relative 'clang/unsaved_file'
|
57
|
+
require_relative 'clang/token'
|
58
|
+
require_relative 'clang/code_completion'
|
59
|
+
require_relative 'clang/compilation_database'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require_relative 'lib/clang_version'
|
22
|
+
|
23
|
+
module FFI
|
24
|
+
module Clang
|
25
|
+
def self.clang_version_string
|
26
|
+
Lib.extract_string Lib.get_clang_version
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/ffi/clang/comment.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
# Copyright, 2013, by Carlos Martín Nieto <cmn@dwim.me>
|
3
2
|
#
|
4
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -19,9 +18,9 @@
|
|
19
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
19
|
# THE SOFTWARE.
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
require_relative 'lib/cursor'
|
22
|
+
require_relative 'lib/comment'
|
23
|
+
require_relative 'source_location'
|
25
24
|
|
26
25
|
module FFI
|
27
26
|
module Clang
|
@@ -205,6 +204,7 @@ module FFI
|
|
205
204
|
def text
|
206
205
|
self.map(&:text).join("")
|
207
206
|
end
|
207
|
+
|
208
208
|
alias_method :comment, :text
|
209
209
|
|
210
210
|
def valid_index?
|
@@ -273,6 +273,10 @@ module FFI
|
|
273
273
|
def to_xml
|
274
274
|
Lib.extract_string Lib.full_comment_get_as_xml(@comment)
|
275
275
|
end
|
276
|
+
|
277
|
+
def text
|
278
|
+
self.children.collect{|child| child.text.strip}.join("\n")
|
279
|
+
end
|
276
280
|
end
|
277
281
|
end
|
278
282
|
end
|
data/lib/ffi/clang/cursor.rb
CHANGED
@@ -20,11 +20,12 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
require_relative 'lib/cursor'
|
24
|
+
require_relative 'lib/code_completion'
|
25
|
+
|
26
|
+
require_relative 'source_location'
|
27
|
+
require_relative 'comment'
|
28
|
+
require_relative 'type'
|
28
29
|
|
29
30
|
module FFI
|
30
31
|
module Clang
|
@@ -238,18 +239,10 @@ module FFI
|
|
238
239
|
Lib.get_language @cursor
|
239
240
|
end
|
240
241
|
|
241
|
-
def translation_unit
|
242
|
-
@translation_unit
|
243
|
-
end
|
244
|
-
|
245
242
|
def num_args
|
246
243
|
Lib.get_num_args @cursor
|
247
244
|
end
|
248
245
|
|
249
|
-
def variadic?
|
250
|
-
Lib.is_variadic(@cursor) != 0
|
251
|
-
end
|
252
|
-
|
253
246
|
def visit_children(&block)
|
254
247
|
adapter = Proc.new do |cxcursor, parent_cursor, unused|
|
255
248
|
block.call Cursor.new(cxcursor, @translation_unit), Cursor.new(parent_cursor, @translation_unit)
|
@@ -348,12 +341,46 @@ module FFI
|
|
348
341
|
Lib.cursor_get_num_arguments(@cursor)
|
349
342
|
end
|
350
343
|
|
351
|
-
attr_reader :cursor
|
352
|
-
|
353
344
|
def ==(other)
|
354
345
|
Lib.are_equal(@cursor, other.cursor) != 0
|
355
346
|
end
|
356
347
|
|
348
|
+
def find_all(*kinds)
|
349
|
+
filter do |child, parent|
|
350
|
+
kinds.include?(child.kind)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def find_first(*kinds)
|
355
|
+
find_all(*kinds).first
|
356
|
+
end
|
357
|
+
|
358
|
+
def filter
|
359
|
+
return to_enum(:select) unless block_given?
|
360
|
+
|
361
|
+
matching = []
|
362
|
+
|
363
|
+
self.visit_children do |child, parent|
|
364
|
+
if yield(child, parent)
|
365
|
+
matching << child
|
366
|
+
end
|
367
|
+
|
368
|
+
:recurse
|
369
|
+
end
|
370
|
+
|
371
|
+
return matching
|
372
|
+
end
|
373
|
+
|
374
|
+
def select
|
375
|
+
filter do |child, parent|
|
376
|
+
yield(child)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def to_a
|
381
|
+
filter.collect{|child, parent| child}
|
382
|
+
end
|
383
|
+
|
357
384
|
class PlatformAvailability < AutoPointer
|
358
385
|
def initialize(memory_pointer)
|
359
386
|
pointer = FFI::Pointer.new(memory_pointer)
|
data/lib/ffi/clang/diagnostic.rb
CHANGED
@@ -20,8 +20,8 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
require_relative 'lib/diagnostic'
|
24
|
+
require_relative 'source_range'
|
25
25
|
|
26
26
|
module FFI
|
27
27
|
module Clang
|
@@ -99,6 +99,10 @@ module FFI
|
|
99
99
|
Lib.get_diagnostic_category(self)
|
100
100
|
end
|
101
101
|
|
102
|
+
def inspect
|
103
|
+
"#{self.location}: #{self.format}"
|
104
|
+
end
|
105
|
+
|
102
106
|
private
|
103
107
|
|
104
108
|
def display_opts(opts)
|
data/lib/ffi/clang/file.rb
CHANGED
@@ -18,23 +18,20 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
|
22
|
-
require 'ffi/clang/utils'
|
21
|
+
require_relative 'lib/file'
|
23
22
|
|
24
23
|
module FFI
|
25
24
|
module Clang
|
26
25
|
class File < Pointer
|
27
26
|
attr_reader :translation_unit
|
28
27
|
|
29
|
-
def initialize(pointer,
|
28
|
+
def initialize(pointer, translation_unit)
|
30
29
|
super pointer
|
31
|
-
@translation_unit =
|
30
|
+
@translation_unit = translation_unit
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@unique_id = Lib::CXFileUniqueID.new(pointer)
|
37
|
-
end
|
32
|
+
pointer = MemoryPointer.new(Lib::CXFileUniqueID)
|
33
|
+
Lib.get_file_unique_id(self, pointer)
|
34
|
+
@unique_id = Lib::CXFileUniqueID.new(pointer)
|
38
35
|
end
|
39
36
|
|
40
37
|
def to_s
|
data/lib/ffi/clang/index.rb
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
|
23
|
+
require_relative 'lib/index'
|
24
24
|
|
25
25
|
module FFI
|
26
26
|
module Clang
|
@@ -45,9 +45,9 @@ module FFI
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def create_translation_unit(ast_filename)
|
48
|
-
|
49
|
-
raise Error, "error parsing #{ast_filename.inspect}" if
|
50
|
-
TranslationUnit.new
|
48
|
+
translation_unit_pointer = Lib.create_translation_unit(self, ast_filename)
|
49
|
+
raise Error, "error parsing #{ast_filename.inspect}" if translation_unit_pointer.null?
|
50
|
+
TranslationUnit.new translation_unit_pointer, self
|
51
51
|
end
|
52
52
|
|
53
53
|
private
|