update 1.0.8.0
Commits for version update
This commit is contained in:
5
vendor/mtdowling/jmespath.php/.gitignore
vendored
Normal file
5
vendor/mtdowling/jmespath.php/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
vendor
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
compiled
|
||||
artifacts/
|
17
vendor/mtdowling/jmespath.php/.travis.yml
vendored
Normal file
17
vendor/mtdowling/jmespath.php/.travis.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- composer install
|
||||
|
||||
script: make test
|
||||
|
||||
after_script:
|
||||
- make perf
|
||||
- JP_PHP_COMPILE=on make perf
|
||||
- JP_PHP_COMPILE=on CACHE=on make perf
|
47
vendor/mtdowling/jmespath.php/CHANGELOG.md
vendored
Normal file
47
vendor/mtdowling/jmespath.php/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 2.3.0 - 2016-01-05
|
||||
|
||||
* Added support for [JEP-9](https://github.com/jmespath/jmespath.site/blob/master/docs/proposals/improved-filters.rst),
|
||||
including unary filter expressions, and `&&` filter expressions.
|
||||
* Fixed various parsing issues, including not removing escaped single quotes
|
||||
from raw string literals.
|
||||
* Added support for the `map` function.
|
||||
* Fixed several issues with code generation.
|
||||
|
||||
## 2.2.0 - 2015-05-27
|
||||
|
||||
* Added support for [JEP-12](https://github.com/jmespath/jmespath.site/blob/master/docs/proposals/raw-string-literals.rst)
|
||||
and raw string literals (e.g., `'foo'`).
|
||||
|
||||
## 2.1.0 - 2014-01-13
|
||||
|
||||
* Added `JmesPath\Env::cleanCompileDir()` to delete any previously compiled
|
||||
JMESPath expressions.
|
||||
|
||||
## 2.0.0 - 2014-01-11
|
||||
|
||||
* Moving to a flattened namespace structure.
|
||||
* Runtimes are now only PHP callables.
|
||||
* Fixed an error in the way empty JSON literals are parsed so that they now
|
||||
return an empty string to match the Python and JavaScript implementations.
|
||||
* Removed functions from runtimes. Instead there is now a function dispatcher
|
||||
class, FnDispatcher, that provides function implementations behind a single
|
||||
dispatch function.
|
||||
* Removed ExprNode in lieu of just using a PHP callable with bound variables.
|
||||
* Removed debug methods from runtimes and instead into a new Debugger class.
|
||||
* Heavily cleaned up function argument validation.
|
||||
* Slice syntax is now properly validated (i.e., colons are followed by the
|
||||
appropriate value).
|
||||
* Lots of code cleanup and performance improvements.
|
||||
* Added a convenient `JmesPath\search()` function.
|
||||
* **IMPORTANT**: Relocating the project to https://github.com/jmespath/jmespath.php
|
||||
|
||||
## 1.1.1 - 2014-10-08
|
||||
|
||||
* Added support for using ArrayAccess and Countable as arrays and objects.
|
||||
|
||||
## 1.1.0 - 2014-08-06
|
||||
|
||||
* Added the ability to search data returned from json_decode() where JSON
|
||||
objects are returned as stdClass objects.
|
19
vendor/mtdowling/jmespath.php/LICENSE
vendored
Normal file
19
vendor/mtdowling/jmespath.php/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
19
vendor/mtdowling/jmespath.php/Makefile
vendored
Normal file
19
vendor/mtdowling/jmespath.php/Makefile
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
all: clean coverage
|
||||
|
||||
test:
|
||||
vendor/bin/phpunit
|
||||
|
||||
coverage:
|
||||
vendor/bin/phpunit --coverage-html=artifacts/coverage
|
||||
|
||||
view-coverage:
|
||||
open artifacts/coverage/index.html
|
||||
|
||||
clean:
|
||||
rm -rf artifacts/*
|
||||
rm -rf compiled/*
|
||||
|
||||
perf:
|
||||
php bin/perf.php
|
||||
|
||||
.PHONY: test coverage perf
|
123
vendor/mtdowling/jmespath.php/README.rst
vendored
Normal file
123
vendor/mtdowling/jmespath.php/README.rst
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
============
|
||||
jmespath.php
|
||||
============
|
||||
|
||||
JMESPath (pronounced "jaymz path") allows you to declaratively specify how to
|
||||
extract elements from a JSON document. *jmespath.php* allows you to use
|
||||
JMESPath in PHP applications with PHP data structures. It requires PHP 5.4 or
|
||||
greater and can be installed through `Composer <http://getcomposer.org/doc/00-intro.md>`_
|
||||
using the ``mtdowling/jmespath.php`` package.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
$expression = 'foo.*.baz';
|
||||
|
||||
$data = [
|
||||
'foo' => [
|
||||
'bar' => ['baz' => 1],
|
||||
'bam' => ['baz' => 2],
|
||||
'boo' => ['baz' => 3]
|
||||
]
|
||||
];
|
||||
|
||||
JmesPath\search($expression, $data);
|
||||
// Returns: [1, 2, 3]
|
||||
|
||||
- `JMESPath Tutorial <http://jmespath.org/tutorial.html>`_
|
||||
- `JMESPath Grammar <http://jmespath.org/specification.html#grammar>`_
|
||||
- `JMESPath Python library <https://github.com/jmespath/jmespath.py>`_
|
||||
|
||||
PHP Usage
|
||||
=========
|
||||
|
||||
The ``JmesPath\search`` function can be used in most cases when using the
|
||||
library. This function utilizes a JMESPath runtime based on your environment.
|
||||
The runtime utilized can be configured using environment variables and may at
|
||||
some point in the future automatically utilize a C extension if available.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$result = JmesPath\search($expression, $data);
|
||||
|
||||
// or, if you require PSR-4 compliance.
|
||||
$result = JmesPath\Env::search($expression, $data);
|
||||
|
||||
Runtimes
|
||||
--------
|
||||
|
||||
jmespath.php utilizes *runtimes*. There are currently two runtimes:
|
||||
AstRuntime and CompilerRuntime.
|
||||
|
||||
AstRuntime is utilized by ``JmesPath\search()`` and ``JmesPath\Env::search()``
|
||||
by default.
|
||||
|
||||
AstRuntime
|
||||
~~~~~~~~~~
|
||||
|
||||
The AstRuntime will parse an expression, cache the resulting AST in memory,
|
||||
and interpret the AST using an external tree visitor. AstRuntime provides a
|
||||
good general approach for interpreting JMESPath expressions that have a low to
|
||||
moderate level of reuse.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$runtime = new JmesPath\AstRuntime();
|
||||
$runtime('foo.bar', ['foo' => ['bar' => 'baz']]);
|
||||
// > 'baz'
|
||||
|
||||
CompilerRuntime
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
``JmesPath\CompilerRuntime`` provides the most performance for
|
||||
applications that have a moderate to high level of reuse of JMESPath
|
||||
expressions. The CompilerRuntime will walk a JMESPath AST and emit PHP source
|
||||
code, resulting in anywhere from 7x to 60x speed improvements.
|
||||
|
||||
Compiling JMESPath expressions to source code is a slower process than just
|
||||
walking and interpreting a JMESPath AST (via the AstRuntime). However,
|
||||
running the compiled JMESPath code results in much better performance than
|
||||
walking an AST. This essentially means that there is a warm-up period when
|
||||
using the ``CompilerRuntime``, but after the warm-up period, it will provide
|
||||
much better performance.
|
||||
|
||||
Use the CompilerRuntime if you know that you will be executing JMESPath
|
||||
expressions more than once or if you can pre-compile JMESPath expressions
|
||||
before executing them (for example, server-side applications).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Note: The cache directory argument is optional.
|
||||
$runtime = new JmesPath\CompilerRuntime('/path/to/compile/folder');
|
||||
$runtime('foo.bar', ['foo' => ['bar' => 'baz']]);
|
||||
// > 'baz'
|
||||
|
||||
Environment Variables
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can utilize the CompilerRuntime in ``JmesPath\search()`` by setting
|
||||
the ``JP_PHP_COMPILE`` environment variable to "on" or to a directory
|
||||
on disk used to store cached expressions.
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
A comprehensive list of test cases can be found at
|
||||
https://github.com/jmespath/jmespath.php/tree/master/tests/compliance.
|
||||
These compliance tests are utilized by jmespath.php to ensure consistency with
|
||||
other implementations, and can serve as examples of the language.
|
||||
|
||||
jmespath.php is tested using PHPUnit. In order to run the tests, you need to
|
||||
first install the dependencies using Composer as described in the *Installation*
|
||||
section. Next you just need to run the tests via make:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make test
|
||||
|
||||
You can run a suite of performance tests as well:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make perf
|
65
vendor/mtdowling/jmespath.php/bin/jp.php
vendored
Normal file
65
vendor/mtdowling/jmespath.php/bin/jp.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use JmesPath\Env;
|
||||
use JmesPath\DebugRuntime;
|
||||
|
||||
$description = <<<EOT
|
||||
Runs a JMESPath expression on the provided input or a test case.
|
||||
|
||||
Provide the JSON input and expression:
|
||||
echo '{}' | jp.php expression
|
||||
|
||||
Or provide the path to a compliance script, a suite, and test case number:
|
||||
jp.php --script path_to_script --suite test_suite_number --case test_case_number [expression]
|
||||
|
||||
EOT;
|
||||
|
||||
$args = [];
|
||||
$currentKey = null;
|
||||
for ($i = 1, $total = count($argv); $i < $total; $i++) {
|
||||
if ($i % 2) {
|
||||
if (substr($argv[$i], 0, 2) == '--') {
|
||||
$currentKey = str_replace('--', '', $argv[$i]);
|
||||
} else {
|
||||
$currentKey = trim($argv[$i]);
|
||||
}
|
||||
} else {
|
||||
$args[$currentKey] = $argv[$i];
|
||||
$currentKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
$expression = $currentKey;
|
||||
|
||||
if (isset($args['file']) || isset($args['suite']) || isset($args['case'])) {
|
||||
if (!isset($args['file']) || !isset($args['suite']) || !isset($args['case'])) {
|
||||
die($description);
|
||||
}
|
||||
// Manually run a compliance test
|
||||
$path = realpath($args['file']);
|
||||
file_exists($path) or die('File not found at ' . $path);
|
||||
$json = json_decode(file_get_contents($path), true);
|
||||
$set = $json[$args['suite']];
|
||||
$data = $set['given'];
|
||||
if (!isset($expression)) {
|
||||
$expression = $set['cases'][$args['case']]['expression'];
|
||||
echo "Expects\n=======\n";
|
||||
if (isset($set['cases'][$args['case']]['result'])) {
|
||||
echo json_encode($set['cases'][$args['case']]['result'], JSON_PRETTY_PRINT) . "\n\n";
|
||||
} elseif (isset($set['cases'][$args['case']]['error'])) {
|
||||
echo "{$set['cases'][$argv['case']]['error']} error\n\n";
|
||||
} else {
|
||||
echo "NULL\n\n";
|
||||
}
|
||||
}
|
||||
} elseif (isset($expression)) {
|
||||
// Pass in an expression and STDIN as a standalone argument
|
||||
$data = json_decode(stream_get_contents(STDIN), true);
|
||||
} else {
|
||||
die($description);
|
||||
}
|
||||
|
||||
$runtime = new DebugRuntime(Env::createRuntime());
|
||||
$runtime($expression, $data);
|
57
vendor/mtdowling/jmespath.php/bin/perf.php
vendored
Normal file
57
vendor/mtdowling/jmespath.php/bin/perf.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$dir = isset($argv[1]) ? $argv[1] : __DIR__ . '/../tests/compliance/perf';
|
||||
is_dir($dir) or die('Dir not found: ' . $dir);
|
||||
// Warm up the runner
|
||||
\JmesPath\Env::search('foo', []);
|
||||
|
||||
$total = 0;
|
||||
foreach (glob($dir . '/*.json') as $file) {
|
||||
$total += runSuite($file);
|
||||
}
|
||||
echo "\nTotal time: {$total}\n";
|
||||
|
||||
function runSuite($file)
|
||||
{
|
||||
$contents = file_get_contents($file);
|
||||
$json = json_decode($contents, true);
|
||||
$total = 0;
|
||||
foreach ($json as $suite) {
|
||||
foreach ($suite['cases'] as $case) {
|
||||
$total += runCase(
|
||||
$suite['given'],
|
||||
$case['expression'],
|
||||
$case['name']
|
||||
);
|
||||
}
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
function runCase($given, $expression, $name)
|
||||
{
|
||||
$best = 99999;
|
||||
$runtime = \JmesPath\Env::createRuntime();
|
||||
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$t = microtime(true);
|
||||
$runtime($expression, $given);
|
||||
$tryTime = (microtime(true) - $t) * 1000;
|
||||
if ($tryTime < $best) {
|
||||
$best = $tryTime;
|
||||
}
|
||||
if (!getenv('CACHE')) {
|
||||
$runtime = \JmesPath\Env::createRuntime();
|
||||
// Delete compiled scripts if not caching.
|
||||
if ($runtime instanceof \JmesPath\CompilerRuntime) {
|
||||
array_map('unlink', glob(sys_get_temp_dir() . '/jmespath_*.php'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("time: %07.4fms name: %s\n", $best, $name);
|
||||
|
||||
return $best;
|
||||
}
|
37
vendor/mtdowling/jmespath.php/composer.json
vendored
Normal file
37
vendor/mtdowling/jmespath.php/composer.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "mtdowling/jmespath.php",
|
||||
"description": "Declaratively specify how to extract elements from a JSON document",
|
||||
"keywords": ["json", "jsonpath"],
|
||||
"license": "MIT",
|
||||
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"JmesPath\\": "src/"
|
||||
},
|
||||
"files": ["src/JmesPath.php"]
|
||||
},
|
||||
|
||||
"bin": ["bin/jp.php"],
|
||||
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
17
vendor/mtdowling/jmespath.php/phpunit.xml.dist
vendored
Normal file
17
vendor/mtdowling/jmespath.php/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="./vendor/autoload.php"
|
||||
colors="true">
|
||||
|
||||
<testsuites>
|
||||
<testsuite>
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
</phpunit>
|
47
vendor/mtdowling/jmespath.php/src/AstRuntime.php
vendored
Normal file
47
vendor/mtdowling/jmespath.php/src/AstRuntime.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Uses an external tree visitor to interpret an AST.
|
||||
*/
|
||||
class AstRuntime
|
||||
{
|
||||
private $parser;
|
||||
private $interpreter;
|
||||
private $cache = [];
|
||||
private $cachedCount = 0;
|
||||
|
||||
public function __construct(
|
||||
Parser $parser = null,
|
||||
callable $fnDispatcher = null
|
||||
) {
|
||||
$fnDispatcher = $fnDispatcher ?: FnDispatcher::getInstance();
|
||||
$this->interpreter = new TreeInterpreter($fnDispatcher);
|
||||
$this->parser = $parser ?: new Parser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data from the provided input that matches a given JMESPath
|
||||
* expression.
|
||||
*
|
||||
* @param string $expression JMESPath expression to evaluate
|
||||
* @param mixed $data Data to search. This data should be data that
|
||||
* is similar to data returned from json_decode
|
||||
* using associative arrays rather than objects.
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
*/
|
||||
public function __invoke($expression, $data)
|
||||
{
|
||||
if (!isset($this->cache[$expression])) {
|
||||
// Clear the AST cache when it hits 1024 entries
|
||||
if (++$this->cachedCount > 1024) {
|
||||
$this->cache = [];
|
||||
$this->cachedCount = 0;
|
||||
}
|
||||
$this->cache[$expression] = $this->parser->parse($expression);
|
||||
}
|
||||
|
||||
return $this->interpreter->visit($this->cache[$expression], $data);
|
||||
}
|
||||
}
|
83
vendor/mtdowling/jmespath.php/src/CompilerRuntime.php
vendored
Normal file
83
vendor/mtdowling/jmespath.php/src/CompilerRuntime.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Compiles JMESPath expressions to PHP source code and executes it.
|
||||
*
|
||||
* JMESPath file names are stored in the cache directory using the following
|
||||
* logic to determine the filename:
|
||||
*
|
||||
* 1. Start with the string "jmespath_"
|
||||
* 2. Append the MD5 checksum of the expression.
|
||||
* 3. Append ".php"
|
||||
*/
|
||||
class CompilerRuntime
|
||||
{
|
||||
private $parser;
|
||||
private $compiler;
|
||||
private $cacheDir;
|
||||
private $interpreter;
|
||||
|
||||
/**
|
||||
* @param string $dir Directory used to store compiled PHP files.
|
||||
* @param Parser $parser JMESPath parser to utilize
|
||||
* @throws \RuntimeException if the cache directory cannot be created
|
||||
*/
|
||||
public function __construct($dir = null, Parser $parser = null)
|
||||
{
|
||||
$this->parser = $parser ?: new Parser();
|
||||
$this->compiler = new TreeCompiler();
|
||||
$dir = $dir ?: sys_get_temp_dir();
|
||||
|
||||
if (!is_dir($dir) && !mkdir($dir, 0755, true)) {
|
||||
throw new \RuntimeException("Unable to create cache directory: $dir");
|
||||
}
|
||||
|
||||
$this->cacheDir = realpath($dir);
|
||||
$this->interpreter = new TreeInterpreter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data from the provided input that matches a given JMESPath
|
||||
* expression.
|
||||
*
|
||||
* @param string $expression JMESPath expression to evaluate
|
||||
* @param mixed $data Data to search. This data should be data that
|
||||
* is similar to data returned from json_decode
|
||||
* using associative arrays rather than objects.
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __invoke($expression, $data)
|
||||
{
|
||||
$functionName = 'jmespath_' . md5($expression);
|
||||
|
||||
if (!function_exists($functionName)) {
|
||||
$filename = "{$this->cacheDir}/{$functionName}.php";
|
||||
if (!file_exists($filename)) {
|
||||
$this->compile($filename, $expression, $functionName);
|
||||
}
|
||||
require $filename;
|
||||
}
|
||||
|
||||
return $functionName($this->interpreter, $data);
|
||||
}
|
||||
|
||||
private function compile($filename, $expression, $functionName)
|
||||
{
|
||||
$code = $this->compiler->visit(
|
||||
$this->parser->parse($expression),
|
||||
$functionName,
|
||||
$expression
|
||||
);
|
||||
|
||||
if (!file_put_contents($filename, $code)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Unable to write the compiled PHP code to: %s (%s)',
|
||||
$filename,
|
||||
var_export(error_get_last(), true)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
109
vendor/mtdowling/jmespath.php/src/DebugRuntime.php
vendored
Normal file
109
vendor/mtdowling/jmespath.php/src/DebugRuntime.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Provides CLI debugging information for the AST and Compiler runtimes.
|
||||
*/
|
||||
class DebugRuntime
|
||||
{
|
||||
private $runtime;
|
||||
private $out;
|
||||
private $lexer;
|
||||
private $parser;
|
||||
|
||||
public function __construct(callable $runtime, $output = null)
|
||||
{
|
||||
$this->runtime = $runtime;
|
||||
$this->out = $output ?: STDOUT;
|
||||
$this->lexer = new Lexer();
|
||||
$this->parser = new Parser($this->lexer);
|
||||
}
|
||||
|
||||
public function __invoke($expression, $data)
|
||||
{
|
||||
if ($this->runtime instanceof CompilerRuntime) {
|
||||
return $this->debugCompiled($expression, $data);
|
||||
}
|
||||
|
||||
return $this->debugInterpreted($expression, $data);
|
||||
}
|
||||
|
||||
private function debugInterpreted($expression, $data)
|
||||
{
|
||||
return $this->debugCallback(
|
||||
function () use ($expression, $data) {
|
||||
$runtime = $this->runtime;
|
||||
return $runtime($expression, $data);
|
||||
},
|
||||
$expression,
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
private function debugCompiled($expression, $data)
|
||||
{
|
||||
$result = $this->debugCallback(
|
||||
function () use ($expression, $data) {
|
||||
$runtime = $this->runtime;
|
||||
return $runtime($expression, $data);
|
||||
},
|
||||
$expression,
|
||||
$data
|
||||
);
|
||||
$this->dumpCompiledCode($expression);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function dumpTokens($expression)
|
||||
{
|
||||
$lexer = new Lexer();
|
||||
fwrite($this->out, "Tokens\n======\n\n");
|
||||
$tokens = $lexer->tokenize($expression);
|
||||
|
||||
foreach ($tokens as $t) {
|
||||
fprintf(
|
||||
$this->out,
|
||||
"%3d %-13s %s\n", $t['pos'], $t['type'],
|
||||
json_encode($t['value'])
|
||||
);
|
||||
}
|
||||
|
||||
fwrite($this->out, "\n");
|
||||
}
|
||||
|
||||
private function dumpAst($expression)
|
||||
{
|
||||
$parser = new Parser();
|
||||
$ast = $parser->parse($expression);
|
||||
fwrite($this->out, "AST\n========\n\n");
|
||||
fwrite($this->out, json_encode($ast, JSON_PRETTY_PRINT) . "\n");
|
||||
}
|
||||
|
||||
private function dumpCompiledCode($expression)
|
||||
{
|
||||
fwrite($this->out, "Code\n========\n\n");
|
||||
$dir = sys_get_temp_dir();
|
||||
$hash = md5($expression);
|
||||
$functionName = "jmespath_{$hash}";
|
||||
$filename = "{$dir}/{$functionName}.php";
|
||||
fwrite($this->out, "File: {$filename}\n\n");
|
||||
fprintf($this->out, file_get_contents($filename));
|
||||
}
|
||||
|
||||
private function debugCallback(callable $debugFn, $expression, $data)
|
||||
{
|
||||
fprintf($this->out, "Expression\n==========\n\n%s\n\n", $expression);
|
||||
$this->dumpTokens($expression);
|
||||
$this->dumpAst($expression);
|
||||
fprintf($this->out, "\nData\n====\n\n%s\n\n", json_encode($data, JSON_PRETTY_PRINT));
|
||||
$startTime = microtime(true);
|
||||
$result = $debugFn();
|
||||
$total = microtime(true) - $startTime;
|
||||
fprintf($this->out, "\nResult\n======\n\n%s\n\n", json_encode($result, JSON_PRETTY_PRINT));
|
||||
fwrite($this->out, "Time\n====\n\n");
|
||||
fprintf($this->out, "Total time: %f ms\n\n", $total);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
66
vendor/mtdowling/jmespath.php/src/Env.php
vendored
Normal file
66
vendor/mtdowling/jmespath.php/src/Env.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Provides a simple environment based search.
|
||||
*
|
||||
* The runtime utilized by the Env class can be customized via environment
|
||||
* variables. If the JP_PHP_COMPILE environment variable is specified, then the
|
||||
* CompilerRuntime will be utilized. If set to "on", JMESPath expressions will
|
||||
* be cached to the system's temp directory. Set the environment variable to
|
||||
* a string to cache expressions to a specific directory.
|
||||
*/
|
||||
final class Env
|
||||
{
|
||||
const COMPILE_DIR = 'JP_PHP_COMPILE';
|
||||
|
||||
/**
|
||||
* Returns data from the input array that matches a JMESPath expression.
|
||||
*
|
||||
* @param string $expression JMESPath expression to evaluate
|
||||
* @param mixed $data JSON-like data to search
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
*/
|
||||
public static function search($expression, $data)
|
||||
{
|
||||
static $runtime;
|
||||
if (!$runtime) {
|
||||
$runtime = Env::createRuntime();
|
||||
}
|
||||
return $runtime($expression, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JMESPath runtime based on environment variables and extensions
|
||||
* available on a system.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public static function createRuntime()
|
||||
{
|
||||
switch ($compileDir = getenv(self::COMPILE_DIR)) {
|
||||
case false: return new AstRuntime();
|
||||
case 'on': return new CompilerRuntime();
|
||||
default: return new CompilerRuntime($compileDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all previously compiled JMESPath files from the JP_COMPILE_DIR
|
||||
* directory or sys_get_temp_dir().
|
||||
*
|
||||
* @return int Returns the number of deleted files.
|
||||
*/
|
||||
public static function cleanCompileDir()
|
||||
{
|
||||
$total = 0;
|
||||
$compileDir = getenv(self::COMPILE_DIR) ?: sys_get_temp_dir();
|
||||
foreach (glob("{$compileDir}/jmespath_*.php") as $file) {
|
||||
$total++;
|
||||
unlink($file);
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
401
vendor/mtdowling/jmespath.php/src/FnDispatcher.php
vendored
Normal file
401
vendor/mtdowling/jmespath.php/src/FnDispatcher.php
vendored
Normal file
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Dispatches to named JMESPath functions using a single function that has the
|
||||
* following signature:
|
||||
*
|
||||
* mixed $result = fn(string $function_name, array $args)
|
||||
*/
|
||||
class FnDispatcher
|
||||
{
|
||||
/**
|
||||
* Gets a cached instance of the default function implementations.
|
||||
*
|
||||
* @return FnDispatcher
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
static $instance = null;
|
||||
if (!$instance) {
|
||||
$instance = new self();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fn Function name.
|
||||
* @param array $args Function arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke($fn, array $args)
|
||||
{
|
||||
return $this->{'fn_' . $fn}($args);
|
||||
}
|
||||
|
||||
private function fn_abs(array $args)
|
||||
{
|
||||
$this->validate('abs', $args, [['number']]);
|
||||
return abs($args[0]);
|
||||
}
|
||||
|
||||
private function fn_avg(array $args)
|
||||
{
|
||||
$this->validate('avg', $args, [['array']]);
|
||||
$sum = $this->reduce('avg:0', $args[0], ['number'], function ($a, $b) {
|
||||
return $a + $b;
|
||||
});
|
||||
return $args[0] ? ($sum / count($args[0])) : null;
|
||||
}
|
||||
|
||||
private function fn_ceil(array $args)
|
||||
{
|
||||
$this->validate('ceil', $args, [['number']]);
|
||||
return ceil($args[0]);
|
||||
}
|
||||
|
||||
private function fn_contains(array $args)
|
||||
{
|
||||
$this->validate('contains', $args, [['string', 'array'], ['any']]);
|
||||
if (is_array($args[0])) {
|
||||
return in_array($args[1], $args[0]);
|
||||
} elseif (is_string($args[1])) {
|
||||
return strpos($args[0], $args[1]) !== false;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function fn_ends_with(array $args)
|
||||
{
|
||||
$this->validate('ends_with', $args, [['string'], ['string']]);
|
||||
list($search, $suffix) = $args;
|
||||
return $suffix === '' || substr($search, -strlen($suffix)) === $suffix;
|
||||
}
|
||||
|
||||
private function fn_floor(array $args)
|
||||
{
|
||||
$this->validate('floor', $args, [['number']]);
|
||||
return floor($args[0]);
|
||||
}
|
||||
|
||||
private function fn_not_null(array $args)
|
||||
{
|
||||
if (!$args) {
|
||||
throw new \RuntimeException(
|
||||
"not_null() expects 1 or more arguments, 0 were provided"
|
||||
);
|
||||
}
|
||||
|
||||
return array_reduce($args, function ($carry, $item) {
|
||||
return $carry !== null ? $carry : $item;
|
||||
});
|
||||
}
|
||||
|
||||
private function fn_join(array $args)
|
||||
{
|
||||
$this->validate('join', $args, [['string'], ['array']]);
|
||||
$fn = function ($a, $b, $i) use ($args) {
|
||||
return $i ? ($a . $args[0] . $b) : $b;
|
||||
};
|
||||
return $this->reduce('join:0', $args[1], ['string'], $fn);
|
||||
}
|
||||
|
||||
private function fn_keys(array $args)
|
||||
{
|
||||
$this->validate('keys', $args, [['object']]);
|
||||
return array_keys((array) $args[0]);
|
||||
}
|
||||
|
||||
private function fn_length(array $args)
|
||||
{
|
||||
$this->validate('length', $args, [['string', 'array', 'object']]);
|
||||
return is_string($args[0]) ? strlen($args[0]) : count((array) $args[0]);
|
||||
}
|
||||
|
||||
private function fn_max(array $args)
|
||||
{
|
||||
$this->validate('max', $args, [['array']]);
|
||||
$fn = function ($a, $b) { return $a >= $b ? $a : $b; };
|
||||
return $this->reduce('max:0', $args[0], ['number', 'string'], $fn);
|
||||
}
|
||||
|
||||
private function fn_max_by(array $args)
|
||||
{
|
||||
$this->validate('max_by', $args, [['array'], ['expression']]);
|
||||
$expr = $this->wrapExpression('max_by:1', $args[1], ['number', 'string']);
|
||||
$fn = function ($carry, $item, $index) use ($expr) {
|
||||
return $index
|
||||
? ($expr($carry) >= $expr($item) ? $carry : $item)
|
||||
: $item;
|
||||
};
|
||||
return $this->reduce('max_by:1', $args[0], ['any'], $fn);
|
||||
}
|
||||
|
||||
private function fn_min(array $args)
|
||||
{
|
||||
$this->validate('min', $args, [['array']]);
|
||||
$fn = function ($a, $b, $i) { return $i && $a <= $b ? $a : $b; };
|
||||
return $this->reduce('min:0', $args[0], ['number', 'string'], $fn);
|
||||
}
|
||||
|
||||
private function fn_min_by(array $args)
|
||||
{
|
||||
$this->validate('min_by', $args, [['array'], ['expression']]);
|
||||
$expr = $this->wrapExpression('min_by:1', $args[1], ['number', 'string']);
|
||||
$i = -1;
|
||||
$fn = function ($a, $b) use ($expr, &$i) {
|
||||
return ++$i ? ($expr($a) <= $expr($b) ? $a : $b) : $b;
|
||||
};
|
||||
return $this->reduce('min_by:1', $args[0], ['any'], $fn);
|
||||
}
|
||||
|
||||
private function fn_reverse(array $args)
|
||||
{
|
||||
$this->validate('reverse', $args, [['array', 'string']]);
|
||||
if (is_array($args[0])) {
|
||||
return array_reverse($args[0]);
|
||||
} elseif (is_string($args[0])) {
|
||||
return strrev($args[0]);
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot reverse provided argument');
|
||||
}
|
||||
}
|
||||
|
||||
private function fn_sum(array $args)
|
||||
{
|
||||
$this->validate('sum', $args, [['array']]);
|
||||
$fn = function ($a, $b) { return $a + $b; };
|
||||
return $this->reduce('sum:0', $args[0], ['number'], $fn);
|
||||
}
|
||||
|
||||
private function fn_sort(array $args)
|
||||
{
|
||||
$this->validate('sort', $args, [['array']]);
|
||||
$valid = ['string', 'number'];
|
||||
return Utils::stableSort($args[0], function ($a, $b) use ($valid) {
|
||||
$this->validateSeq('sort:0', $valid, $a, $b);
|
||||
return strnatcmp($a, $b);
|
||||
});
|
||||
}
|
||||
|
||||
private function fn_sort_by(array $args)
|
||||
{
|
||||
$this->validate('sort_by', $args, [['array'], ['expression']]);
|
||||
$expr = $args[1];
|
||||
$valid = ['string', 'number'];
|
||||
return Utils::stableSort(
|
||||
$args[0],
|
||||
function ($a, $b) use ($expr, $valid) {
|
||||
$va = $expr($a);
|
||||
$vb = $expr($b);
|
||||
$this->validateSeq('sort_by:0', $valid, $va, $vb);
|
||||
return strnatcmp($va, $vb);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private function fn_starts_with(array $args)
|
||||
{
|
||||
$this->validate('starts_with', $args, [['string'], ['string']]);
|
||||
list($search, $prefix) = $args;
|
||||
return $prefix === '' || strpos($search, $prefix) === 0;
|
||||
}
|
||||
|
||||
private function fn_type(array $args)
|
||||
{
|
||||
$this->validateArity('type', count($args), 1);
|
||||
return Utils::type($args[0]);
|
||||
}
|
||||
|
||||
private function fn_to_string(array $args)
|
||||
{
|
||||
$this->validateArity('to_string', count($args), 1);
|
||||
$v = $args[0];
|
||||
if (is_string($v)) {
|
||||
return $v;
|
||||
} elseif (is_object($v)
|
||||
&& !($v instanceof \JsonSerializable)
|
||||
&& method_exists($v, '__toString')
|
||||
) {
|
||||
return (string) $v;
|
||||
}
|
||||
|
||||
return json_encode($v);
|
||||
}
|
||||
|
||||
private function fn_to_number(array $args)
|
||||
{
|
||||
$this->validateArity('to_number', count($args), 1);
|
||||
$value = $args[0];
|
||||
$type = Utils::type($value);
|
||||
if ($type == 'number') {
|
||||
return $value;
|
||||
} elseif ($type == 'string' && is_numeric($value)) {
|
||||
return strpos($value, '.') ? (float) $value : (int) $value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function fn_values(array $args)
|
||||
{
|
||||
$this->validate('values', $args, [['array', 'object']]);
|
||||
return array_values((array) $args[0]);
|
||||
}
|
||||
|
||||
private function fn_merge(array $args)
|
||||
{
|
||||
if (!$args) {
|
||||
throw new \RuntimeException(
|
||||
"merge() expects 1 or more arguments, 0 were provided"
|
||||
);
|
||||
}
|
||||
|
||||
return call_user_func_array('array_replace', $args);
|
||||
}
|
||||
|
||||
private function fn_to_array(array $args)
|
||||
{
|
||||
$this->validate('to_array', $args, [['any']]);
|
||||
|
||||
return Utils::isArray($args[0]) ? $args[0] : [$args[0]];
|
||||
}
|
||||
|
||||
private function fn_map(array $args)
|
||||
{
|
||||
$this->validate('map', $args, [['expression'], ['any']]);
|
||||
$result = [];
|
||||
foreach ($args[1] as $a) {
|
||||
$result[] = $args[0]($a);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function typeError($from, $msg)
|
||||
{
|
||||
if (strpos($from, ':')) {
|
||||
list($fn, $pos) = explode(':', $from);
|
||||
throw new \RuntimeException(
|
||||
sprintf('Argument %d of %s %s', $pos, $fn, $msg)
|
||||
);
|
||||
} else {
|
||||
throw new \RuntimeException(
|
||||
sprintf('Type error: %s %s', $from, $msg)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateArity($from, $given, $expected)
|
||||
{
|
||||
if ($given != $expected) {
|
||||
$err = "%s() expects {$expected} arguments, {$given} were provided";
|
||||
throw new \RuntimeException(sprintf($err, $from));
|
||||
}
|
||||
}
|
||||
|
||||
private function validate($from, $args, $types = [])
|
||||
{
|
||||
$this->validateArity($from, count($args), count($types));
|
||||
foreach ($args as $index => $value) {
|
||||
if (!isset($types[$index]) || !$types[$index]) {
|
||||
continue;
|
||||
}
|
||||
$this->validateType("{$from}:{$index}", $value, $types[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateType($from, $value, array $types)
|
||||
{
|
||||
if ($types[0] == 'any'
|
||||
|| in_array(Utils::type($value), $types)
|
||||
|| ($value === [] && in_array('object', $types))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
$msg = 'must be one of the following types: ' . implode(', ', $types)
|
||||
. '. ' . Utils::type($value) . ' found';
|
||||
$this->typeError($from, $msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates value A and B, ensures they both are correctly typed, and of
|
||||
* the same type.
|
||||
*
|
||||
* @param string $from String of function:argument_position
|
||||
* @param array $types Array of valid value types.
|
||||
* @param mixed $a Value A
|
||||
* @param mixed $b Value B
|
||||
*/
|
||||
private function validateSeq($from, array $types, $a, $b)
|
||||
{
|
||||
$ta = Utils::type($a);
|
||||
$tb = Utils::type($b);
|
||||
|
||||
if ($ta !== $tb) {
|
||||
$msg = "encountered a type mismatch in sequence: {$ta}, {$tb}";
|
||||
$this->typeError($from, $msg);
|
||||
}
|
||||
|
||||
$typeMatch = ($types && $types[0] == 'any') || in_array($ta, $types);
|
||||
if (!$typeMatch) {
|
||||
$msg = 'encountered a type error in sequence. The argument must be '
|
||||
. 'an array of ' . implode('|', $types) . ' types. '
|
||||
. "Found {$ta}, {$tb}.";
|
||||
$this->typeError($from, $msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces and validates an array of values to a single value using a fn.
|
||||
*
|
||||
* @param string $from String of function:argument_position
|
||||
* @param array $values Values to reduce.
|
||||
* @param array $types Array of valid value types.
|
||||
* @param callable $reduce Reduce function that accepts ($carry, $item).
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function reduce($from, array $values, array $types, callable $reduce)
|
||||
{
|
||||
$i = -1;
|
||||
return array_reduce(
|
||||
$values,
|
||||
function ($carry, $item) use ($from, $types, $reduce, &$i) {
|
||||
if (++$i > 0) {
|
||||
$this->validateSeq($from, $types, $carry, $item);
|
||||
}
|
||||
return $reduce($carry, $item, $i);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the return values of expressions as they are applied.
|
||||
*
|
||||
* @param string $from Function name : position
|
||||
* @param callable $expr Expression function to validate.
|
||||
* @param array $types Array of acceptable return type values.
|
||||
*
|
||||
* @return callable Returns a wrapped function
|
||||
*/
|
||||
private function wrapExpression($from, callable $expr, array $types)
|
||||
{
|
||||
list($fn, $pos) = explode(':', $from);
|
||||
$from = "The expression return value of argument {$pos} of {$fn}";
|
||||
return function ($value) use ($from, $expr, $types) {
|
||||
$value = $expr($value);
|
||||
$this->validateType($from, $value, $types);
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
/** @internal Pass function name validation off to runtime */
|
||||
public function __call($name, $args)
|
||||
{
|
||||
$name = str_replace('fn_', '', $name);
|
||||
throw new \RuntimeException("Call to undefined function {$name}");
|
||||
}
|
||||
}
|
15
vendor/mtdowling/jmespath.php/src/JmesPath.php
vendored
Normal file
15
vendor/mtdowling/jmespath.php/src/JmesPath.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Returns data from the input array that matches a JMESPath expression.
|
||||
*
|
||||
* @param string $expression Expression to search.
|
||||
* @param mixed $data Data to search.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
function search($expression, $data)
|
||||
{
|
||||
return Env::search($expression, $data);
|
||||
}
|
444
vendor/mtdowling/jmespath.php/src/Lexer.php
vendored
Normal file
444
vendor/mtdowling/jmespath.php/src/Lexer.php
vendored
Normal file
@@ -0,0 +1,444 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Tokenizes JMESPath expressions
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
const T_DOT = 'dot';
|
||||
const T_STAR = 'star';
|
||||
const T_COMMA = 'comma';
|
||||
const T_COLON = 'colon';
|
||||
const T_CURRENT = 'current';
|
||||
const T_EXPREF = 'expref';
|
||||
const T_LPAREN = 'lparen';
|
||||
const T_RPAREN = 'rparen';
|
||||
const T_LBRACE = 'lbrace';
|
||||
const T_RBRACE = 'rbrace';
|
||||
const T_LBRACKET = 'lbracket';
|
||||
const T_RBRACKET = 'rbracket';
|
||||
const T_FLATTEN = 'flatten';
|
||||
const T_IDENTIFIER = 'identifier';
|
||||
const T_NUMBER = 'number';
|
||||
const T_QUOTED_IDENTIFIER = 'quoted_identifier';
|
||||
const T_UNKNOWN = 'unknown';
|
||||
const T_PIPE = 'pipe';
|
||||
const T_OR = 'or';
|
||||
const T_AND = 'and';
|
||||
const T_NOT = 'not';
|
||||
const T_FILTER = 'filter';
|
||||
const T_LITERAL = 'literal';
|
||||
const T_EOF = 'eof';
|
||||
const T_COMPARATOR = 'comparator';
|
||||
|
||||
const STATE_IDENTIFIER = 0;
|
||||
const STATE_NUMBER = 1;
|
||||
const STATE_SINGLE_CHAR = 2;
|
||||
const STATE_WHITESPACE = 3;
|
||||
const STATE_STRING_LITERAL = 4;
|
||||
const STATE_QUOTED_STRING = 5;
|
||||
const STATE_JSON_LITERAL = 6;
|
||||
const STATE_LBRACKET = 7;
|
||||
const STATE_PIPE = 8;
|
||||
const STATE_LT = 9;
|
||||
const STATE_GT = 10;
|
||||
const STATE_EQ = 11;
|
||||
const STATE_NOT = 12;
|
||||
const STATE_AND = 13;
|
||||
|
||||
/** @var array We know what token we are consuming based on each char */
|
||||
private static $transitionTable = [
|
||||
'<' => self::STATE_LT,
|
||||
'>' => self::STATE_GT,
|
||||
'=' => self::STATE_EQ,
|
||||
'!' => self::STATE_NOT,
|
||||
'[' => self::STATE_LBRACKET,
|
||||
'|' => self::STATE_PIPE,
|
||||
'&' => self::STATE_AND,
|
||||
'`' => self::STATE_JSON_LITERAL,
|
||||
'"' => self::STATE_QUOTED_STRING,
|
||||
"'" => self::STATE_STRING_LITERAL,
|
||||
'-' => self::STATE_NUMBER,
|
||||
'0' => self::STATE_NUMBER,
|
||||
'1' => self::STATE_NUMBER,
|
||||
'2' => self::STATE_NUMBER,
|
||||
'3' => self::STATE_NUMBER,
|
||||
'4' => self::STATE_NUMBER,
|
||||
'5' => self::STATE_NUMBER,
|
||||
'6' => self::STATE_NUMBER,
|
||||
'7' => self::STATE_NUMBER,
|
||||
'8' => self::STATE_NUMBER,
|
||||
'9' => self::STATE_NUMBER,
|
||||
' ' => self::STATE_WHITESPACE,
|
||||
"\t" => self::STATE_WHITESPACE,
|
||||
"\n" => self::STATE_WHITESPACE,
|
||||
"\r" => self::STATE_WHITESPACE,
|
||||
'.' => self::STATE_SINGLE_CHAR,
|
||||
'*' => self::STATE_SINGLE_CHAR,
|
||||
']' => self::STATE_SINGLE_CHAR,
|
||||
',' => self::STATE_SINGLE_CHAR,
|
||||
':' => self::STATE_SINGLE_CHAR,
|
||||
'@' => self::STATE_SINGLE_CHAR,
|
||||
'(' => self::STATE_SINGLE_CHAR,
|
||||
')' => self::STATE_SINGLE_CHAR,
|
||||
'{' => self::STATE_SINGLE_CHAR,
|
||||
'}' => self::STATE_SINGLE_CHAR,
|
||||
'_' => self::STATE_IDENTIFIER,
|
||||
'A' => self::STATE_IDENTIFIER,
|
||||
'B' => self::STATE_IDENTIFIER,
|
||||
'C' => self::STATE_IDENTIFIER,
|
||||
'D' => self::STATE_IDENTIFIER,
|
||||
'E' => self::STATE_IDENTIFIER,
|
||||
'F' => self::STATE_IDENTIFIER,
|
||||
'G' => self::STATE_IDENTIFIER,
|
||||
'H' => self::STATE_IDENTIFIER,
|
||||
'I' => self::STATE_IDENTIFIER,
|
||||
'J' => self::STATE_IDENTIFIER,
|
||||
'K' => self::STATE_IDENTIFIER,
|
||||
'L' => self::STATE_IDENTIFIER,
|
||||
'M' => self::STATE_IDENTIFIER,
|
||||
'N' => self::STATE_IDENTIFIER,
|
||||
'O' => self::STATE_IDENTIFIER,
|
||||
'P' => self::STATE_IDENTIFIER,
|
||||
'Q' => self::STATE_IDENTIFIER,
|
||||
'R' => self::STATE_IDENTIFIER,
|
||||
'S' => self::STATE_IDENTIFIER,
|
||||
'T' => self::STATE_IDENTIFIER,
|
||||
'U' => self::STATE_IDENTIFIER,
|
||||
'V' => self::STATE_IDENTIFIER,
|
||||
'W' => self::STATE_IDENTIFIER,
|
||||
'X' => self::STATE_IDENTIFIER,
|
||||
'Y' => self::STATE_IDENTIFIER,
|
||||
'Z' => self::STATE_IDENTIFIER,
|
||||
'a' => self::STATE_IDENTIFIER,
|
||||
'b' => self::STATE_IDENTIFIER,
|
||||
'c' => self::STATE_IDENTIFIER,
|
||||
'd' => self::STATE_IDENTIFIER,
|
||||
'e' => self::STATE_IDENTIFIER,
|
||||
'f' => self::STATE_IDENTIFIER,
|
||||
'g' => self::STATE_IDENTIFIER,
|
||||
'h' => self::STATE_IDENTIFIER,
|
||||
'i' => self::STATE_IDENTIFIER,
|
||||
'j' => self::STATE_IDENTIFIER,
|
||||
'k' => self::STATE_IDENTIFIER,
|
||||
'l' => self::STATE_IDENTIFIER,
|
||||
'm' => self::STATE_IDENTIFIER,
|
||||
'n' => self::STATE_IDENTIFIER,
|
||||
'o' => self::STATE_IDENTIFIER,
|
||||
'p' => self::STATE_IDENTIFIER,
|
||||
'q' => self::STATE_IDENTIFIER,
|
||||
'r' => self::STATE_IDENTIFIER,
|
||||
's' => self::STATE_IDENTIFIER,
|
||||
't' => self::STATE_IDENTIFIER,
|
||||
'u' => self::STATE_IDENTIFIER,
|
||||
'v' => self::STATE_IDENTIFIER,
|
||||
'w' => self::STATE_IDENTIFIER,
|
||||
'x' => self::STATE_IDENTIFIER,
|
||||
'y' => self::STATE_IDENTIFIER,
|
||||
'z' => self::STATE_IDENTIFIER,
|
||||
];
|
||||
|
||||
/** @var array Valid identifier characters after first character */
|
||||
private $validIdentifier = [
|
||||
'A' => true, 'B' => true, 'C' => true, 'D' => true, 'E' => true,
|
||||
'F' => true, 'G' => true, 'H' => true, 'I' => true, 'J' => true,
|
||||
'K' => true, 'L' => true, 'M' => true, 'N' => true, 'O' => true,
|
||||
'P' => true, 'Q' => true, 'R' => true, 'S' => true, 'T' => true,
|
||||
'U' => true, 'V' => true, 'W' => true, 'X' => true, 'Y' => true,
|
||||
'Z' => true, 'a' => true, 'b' => true, 'c' => true, 'd' => true,
|
||||
'e' => true, 'f' => true, 'g' => true, 'h' => true, 'i' => true,
|
||||
'j' => true, 'k' => true, 'l' => true, 'm' => true, 'n' => true,
|
||||
'o' => true, 'p' => true, 'q' => true, 'r' => true, 's' => true,
|
||||
't' => true, 'u' => true, 'v' => true, 'w' => true, 'x' => true,
|
||||
'y' => true, 'z' => true, '_' => true, '0' => true, '1' => true,
|
||||
'2' => true, '3' => true, '4' => true, '5' => true, '6' => true,
|
||||
'7' => true, '8' => true, '9' => true,
|
||||
];
|
||||
|
||||
/** @var array Valid number characters after the first character */
|
||||
private $numbers = [
|
||||
'0' => true, '1' => true, '2' => true, '3' => true, '4' => true,
|
||||
'5' => true, '6' => true, '7' => true, '8' => true, '9' => true
|
||||
];
|
||||
|
||||
/** @var array Map of simple single character tokens */
|
||||
private $simpleTokens = [
|
||||
'.' => self::T_DOT,
|
||||
'*' => self::T_STAR,
|
||||
']' => self::T_RBRACKET,
|
||||
',' => self::T_COMMA,
|
||||
':' => self::T_COLON,
|
||||
'@' => self::T_CURRENT,
|
||||
'(' => self::T_LPAREN,
|
||||
')' => self::T_RPAREN,
|
||||
'{' => self::T_LBRACE,
|
||||
'}' => self::T_RBRACE,
|
||||
];
|
||||
|
||||
/**
|
||||
* Tokenize the JMESPath expression into an array of tokens hashes that
|
||||
* contain a 'type', 'value', and 'key'.
|
||||
*
|
||||
* @param string $input JMESPath input
|
||||
*
|
||||
* @return array
|
||||
* @throws SyntaxErrorException
|
||||
*/
|
||||
public function tokenize($input)
|
||||
{
|
||||
$tokens = [];
|
||||
|
||||
if ($input === '') {
|
||||
goto eof;
|
||||
}
|
||||
|
||||
$chars = str_split($input);
|
||||
|
||||
while (false !== ($current = current($chars))) {
|
||||
|
||||
// Every character must be in the transition character table.
|
||||
if (!isset(self::$transitionTable[$current])) {
|
||||
$tokens[] = [
|
||||
'type' => self::T_UNKNOWN,
|
||||
'pos' => key($chars),
|
||||
'value' => $current
|
||||
];
|
||||
next($chars);
|
||||
continue;
|
||||
}
|
||||
|
||||
$state = self::$transitionTable[$current];
|
||||
|
||||
if ($state === self::STATE_SINGLE_CHAR) {
|
||||
|
||||
// Consume simple tokens like ".", ",", "@", etc.
|
||||
$tokens[] = [
|
||||
'type' => $this->simpleTokens[$current],
|
||||
'pos' => key($chars),
|
||||
'value' => $current
|
||||
];
|
||||
next($chars);
|
||||
|
||||
} elseif ($state === self::STATE_IDENTIFIER) {
|
||||
|
||||
// Consume identifiers
|
||||
$start = key($chars);
|
||||
$buffer = '';
|
||||
do {
|
||||
$buffer .= $current;
|
||||
$current = next($chars);
|
||||
} while ($current !== false && isset($this->validIdentifier[$current]));
|
||||
$tokens[] = [
|
||||
'type' => self::T_IDENTIFIER,
|
||||
'value' => $buffer,
|
||||
'pos' => $start
|
||||
];
|
||||
|
||||
} elseif ($state === self::STATE_WHITESPACE) {
|
||||
|
||||
// Skip whitespace
|
||||
next($chars);
|
||||
|
||||
} elseif ($state === self::STATE_LBRACKET) {
|
||||
|
||||
// Consume "[", "[?", and "[]"
|
||||
$position = key($chars);
|
||||
$actual = next($chars);
|
||||
if ($actual === ']') {
|
||||
next($chars);
|
||||
$tokens[] = [
|
||||
'type' => self::T_FLATTEN,
|
||||
'pos' => $position,
|
||||
'value' => '[]'
|
||||
];
|
||||
} elseif ($actual === '?') {
|
||||
next($chars);
|
||||
$tokens[] = [
|
||||
'type' => self::T_FILTER,
|
||||
'pos' => $position,
|
||||
'value' => '[?'
|
||||
];
|
||||
} else {
|
||||
$tokens[] = [
|
||||
'type' => self::T_LBRACKET,
|
||||
'pos' => $position,
|
||||
'value' => '['
|
||||
];
|
||||
}
|
||||
|
||||
} elseif ($state === self::STATE_STRING_LITERAL) {
|
||||
|
||||
// Consume raw string literals
|
||||
$t = $this->inside($chars, "'", self::T_LITERAL);
|
||||
$t['value'] = str_replace("\\'", "'", $t['value']);
|
||||
$tokens[] = $t;
|
||||
|
||||
} elseif ($state === self::STATE_PIPE) {
|
||||
|
||||
// Consume pipe and OR
|
||||
$tokens[] = $this->matchOr($chars, '|', '|', self::T_OR, self::T_PIPE);
|
||||
|
||||
} elseif ($state == self::STATE_JSON_LITERAL) {
|
||||
|
||||
// Consume JSON literals
|
||||
$token = $this->inside($chars, '`', self::T_LITERAL);
|
||||
if ($token['type'] === self::T_LITERAL) {
|
||||
$token['value'] = str_replace('\\`', '`', $token['value']);
|
||||
$token = $this->parseJson($token);
|
||||
}
|
||||
$tokens[] = $token;
|
||||
|
||||
} elseif ($state == self::STATE_NUMBER) {
|
||||
|
||||
// Consume numbers
|
||||
$start = key($chars);
|
||||
$buffer = '';
|
||||
do {
|
||||
$buffer .= $current;
|
||||
$current = next($chars);
|
||||
} while ($current !== false && isset($this->numbers[$current]));
|
||||
$tokens[] = [
|
||||
'type' => self::T_NUMBER,
|
||||
'value' => (int)$buffer,
|
||||
'pos' => $start
|
||||
];
|
||||
|
||||
} elseif ($state === self::STATE_QUOTED_STRING) {
|
||||
|
||||
// Consume quoted identifiers
|
||||
$token = $this->inside($chars, '"', self::T_QUOTED_IDENTIFIER);
|
||||
if ($token['type'] === self::T_QUOTED_IDENTIFIER) {
|
||||
$token['value'] = '"' . $token['value'] . '"';
|
||||
$token = $this->parseJson($token);
|
||||
}
|
||||
$tokens[] = $token;
|
||||
|
||||
} elseif ($state === self::STATE_EQ) {
|
||||
|
||||
// Consume equals
|
||||
$tokens[] = $this->matchOr($chars, '=', '=', self::T_COMPARATOR, self::T_UNKNOWN);
|
||||
|
||||
} elseif ($state == self::STATE_AND) {
|
||||
|
||||
$tokens[] = $this->matchOr($chars, '&', '&', self::T_AND, self::T_EXPREF);
|
||||
|
||||
} elseif ($state === self::STATE_NOT) {
|
||||
|
||||
// Consume not equal
|
||||
$tokens[] = $this->matchOr($chars, '!', '=', self::T_COMPARATOR, self::T_NOT);
|
||||
|
||||
} else {
|
||||
|
||||
// either '<' or '>'
|
||||
// Consume less than and greater than
|
||||
$tokens[] = $this->matchOr($chars, $current, '=', self::T_COMPARATOR, self::T_COMPARATOR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
eof:
|
||||
$tokens[] = [
|
||||
'type' => self::T_EOF,
|
||||
'pos' => strlen($input),
|
||||
'value' => null
|
||||
];
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a token based on whether or not the next token matches the
|
||||
* expected value. If it does, a token of "$type" is returned. Otherwise,
|
||||
* a token of "$orElse" type is returned.
|
||||
*
|
||||
* @param array $chars Array of characters by reference.
|
||||
* @param string $current The current character.
|
||||
* @param string $expected Expected character.
|
||||
* @param string $type Expected result type.
|
||||
* @param string $orElse Otherwise return a token of this type.
|
||||
*
|
||||
* @return array Returns a conditional token.
|
||||
*/
|
||||
private function matchOr(array &$chars, $current, $expected, $type, $orElse)
|
||||
{
|
||||
if (next($chars) === $expected) {
|
||||
next($chars);
|
||||
return [
|
||||
'type' => $type,
|
||||
'pos' => key($chars) - 1,
|
||||
'value' => $current . $expected
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $orElse,
|
||||
'pos' => key($chars) - 1,
|
||||
'value' => $current
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a token the is the result of consuming inside of delimiter
|
||||
* characters. Escaped delimiters will be adjusted before returning a
|
||||
* value. If the token is not closed, "unknown" is returned.
|
||||
*
|
||||
* @param array $chars Array of characters by reference.
|
||||
* @param string $delim The delimiter character.
|
||||
* @param string $type Token type.
|
||||
*
|
||||
* @return array Returns the consumed token.
|
||||
*/
|
||||
private function inside(array &$chars, $delim, $type)
|
||||
{
|
||||
$position = key($chars);
|
||||
$current = next($chars);
|
||||
$buffer = '';
|
||||
|
||||
while ($current !== $delim) {
|
||||
if ($current === '\\') {
|
||||
$buffer .= '\\';
|
||||
$current = next($chars);
|
||||
}
|
||||
if ($current === false) {
|
||||
// Unclosed delimiter
|
||||
return [
|
||||
'type' => self::T_UNKNOWN,
|
||||
'value' => $buffer,
|
||||
'pos' => $position
|
||||
];
|
||||
}
|
||||
$buffer .= $current;
|
||||
$current = next($chars);
|
||||
}
|
||||
|
||||
next($chars);
|
||||
|
||||
return ['type' => $type, 'value' => $buffer, 'pos' => $position];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON token or sets the token type to "unknown" on error.
|
||||
*
|
||||
* @param array $token Token that needs parsing.
|
||||
*
|
||||
* @return array Returns a token with a parsed value.
|
||||
*/
|
||||
private function parseJson(array $token)
|
||||
{
|
||||
$value = json_decode($token['value'], true);
|
||||
|
||||
if ($error = json_last_error()) {
|
||||
// Legacy support for elided quotes. Try to parse again by adding
|
||||
// quotes around the bad input value.
|
||||
$value = json_decode('"' . $token['value'] . '"', true);
|
||||
if ($error = json_last_error()) {
|
||||
$token['type'] = self::T_UNKNOWN;
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
$token['value'] = $value;
|
||||
return $token;
|
||||
}
|
||||
}
|
518
vendor/mtdowling/jmespath.php/src/Parser.php
vendored
Normal file
518
vendor/mtdowling/jmespath.php/src/Parser.php
vendored
Normal file
@@ -0,0 +1,518 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
use JmesPath\Lexer as T;
|
||||
|
||||
/**
|
||||
* JMESPath Pratt parser
|
||||
* @link http://hall.org.ua/halls/wizzard/pdf/Vaughan.Pratt.TDOP.pdf
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
/** @var Lexer */
|
||||
private $lexer;
|
||||
private $tokens;
|
||||
private $token;
|
||||
private $tpos;
|
||||
private $expression;
|
||||
private static $nullToken = ['type' => T::T_EOF];
|
||||
private static $currentNode = ['type' => T::T_CURRENT];
|
||||
|
||||
private static $bp = [
|
||||
T::T_EOF => 0,
|
||||
T::T_QUOTED_IDENTIFIER => 0,
|
||||
T::T_IDENTIFIER => 0,
|
||||
T::T_RBRACKET => 0,
|
||||
T::T_RPAREN => 0,
|
||||
T::T_COMMA => 0,
|
||||
T::T_RBRACE => 0,
|
||||
T::T_NUMBER => 0,
|
||||
T::T_CURRENT => 0,
|
||||
T::T_EXPREF => 0,
|
||||
T::T_COLON => 0,
|
||||
T::T_PIPE => 1,
|
||||
T::T_OR => 2,
|
||||
T::T_AND => 3,
|
||||
T::T_COMPARATOR => 5,
|
||||
T::T_FLATTEN => 9,
|
||||
T::T_STAR => 20,
|
||||
T::T_FILTER => 21,
|
||||
T::T_DOT => 40,
|
||||
T::T_NOT => 45,
|
||||
T::T_LBRACE => 50,
|
||||
T::T_LBRACKET => 55,
|
||||
T::T_LPAREN => 60,
|
||||
];
|
||||
|
||||
/** @var array Acceptable tokens after a dot token */
|
||||
private static $afterDot = [
|
||||
T::T_IDENTIFIER => true, // foo.bar
|
||||
T::T_QUOTED_IDENTIFIER => true, // foo."bar"
|
||||
T::T_STAR => true, // foo.*
|
||||
T::T_LBRACE => true, // foo[1]
|
||||
T::T_LBRACKET => true, // foo{a: 0}
|
||||
T::T_FILTER => true, // foo.[?bar==10]
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Lexer $lexer Lexer used to tokenize expressions
|
||||
*/
|
||||
public function __construct(Lexer $lexer = null)
|
||||
{
|
||||
$this->lexer = $lexer ?: new Lexer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JMESPath expression into an AST
|
||||
*
|
||||
* @param string $expression JMESPath expression to compile
|
||||
*
|
||||
* @return array Returns an array based AST
|
||||
* @throws SyntaxErrorException
|
||||
*/
|
||||
public function parse($expression)
|
||||
{
|
||||
$this->expression = $expression;
|
||||
$this->tokens = $this->lexer->tokenize($expression);
|
||||
$this->tpos = -1;
|
||||
$this->next();
|
||||
$result = $this->expr();
|
||||
|
||||
if ($this->token['type'] === T::T_EOF) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw $this->syntax('Did not reach the end of the token stream');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an expression while rbp < lbp.
|
||||
*
|
||||
* @param int $rbp Right bound precedence
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function expr($rbp = 0)
|
||||
{
|
||||
$left = $this->{"nud_{$this->token['type']}"}();
|
||||
while ($rbp < self::$bp[$this->token['type']]) {
|
||||
$left = $this->{"led_{$this->token['type']}"}($left);
|
||||
}
|
||||
|
||||
return $left;
|
||||
}
|
||||
|
||||
private function nud_identifier()
|
||||
{
|
||||
$token = $this->token;
|
||||
$this->next();
|
||||
return ['type' => 'field', 'value' => $token['value']];
|
||||
}
|
||||
|
||||
private function nud_quoted_identifier()
|
||||
{
|
||||
$token = $this->token;
|
||||
$this->next();
|
||||
$this->assertNotToken(T::T_LPAREN);
|
||||
return ['type' => 'field', 'value' => $token['value']];
|
||||
}
|
||||
|
||||
private function nud_current()
|
||||
{
|
||||
$this->next();
|
||||
return self::$currentNode;
|
||||
}
|
||||
|
||||
private function nud_literal()
|
||||
{
|
||||
$token = $this->token;
|
||||
$this->next();
|
||||
return ['type' => 'literal', 'value' => $token['value']];
|
||||
}
|
||||
|
||||
private function nud_expref()
|
||||
{
|
||||
$this->next();
|
||||
return ['type' => T::T_EXPREF, 'children' => [$this->expr(self::$bp[T::T_EXPREF])]];
|
||||
}
|
||||
|
||||
private function nud_not()
|
||||
{
|
||||
$this->next();
|
||||
return ['type' => T::T_NOT, 'children' => [$this->expr(self::$bp[T::T_NOT])]];
|
||||
}
|
||||
|
||||
private function nud_lparen() {
|
||||
$this->next();
|
||||
$result = $this->expr(0);
|
||||
if ($this->token['type'] !== T::T_RPAREN) {
|
||||
throw $this->syntax('Unclosed `(`');
|
||||
}
|
||||
$this->next();
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function nud_lbrace()
|
||||
{
|
||||
static $validKeys = [T::T_QUOTED_IDENTIFIER => true, T::T_IDENTIFIER => true];
|
||||
$this->next($validKeys);
|
||||
$pairs = [];
|
||||
|
||||
do {
|
||||
$pairs[] = $this->parseKeyValuePair();
|
||||
if ($this->token['type'] == T::T_COMMA) {
|
||||
$this->next($validKeys);
|
||||
}
|
||||
} while ($this->token['type'] !== T::T_RBRACE);
|
||||
|
||||
$this->next();
|
||||
|
||||
return['type' => 'multi_select_hash', 'children' => $pairs];
|
||||
}
|
||||
|
||||
private function nud_flatten()
|
||||
{
|
||||
return $this->led_flatten(self::$currentNode);
|
||||
}
|
||||
|
||||
private function nud_filter()
|
||||
{
|
||||
return $this->led_filter(self::$currentNode);
|
||||
}
|
||||
|
||||
private function nud_star()
|
||||
{
|
||||
return $this->parseWildcardObject(self::$currentNode);
|
||||
}
|
||||
|
||||
private function nud_lbracket()
|
||||
{
|
||||
$this->next();
|
||||
$type = $this->token['type'];
|
||||
if ($type == T::T_NUMBER || $type == T::T_COLON) {
|
||||
return $this->parseArrayIndexExpression();
|
||||
} elseif ($type == T::T_STAR && $this->lookahead() == T::T_RBRACKET) {
|
||||
return $this->parseWildcardArray();
|
||||
} else {
|
||||
return $this->parseMultiSelectList();
|
||||
}
|
||||
}
|
||||
|
||||
private function led_lbracket(array $left)
|
||||
{
|
||||
static $nextTypes = [T::T_NUMBER => true, T::T_COLON => true, T::T_STAR => true];
|
||||
$this->next($nextTypes);
|
||||
switch ($this->token['type']) {
|
||||
case T::T_NUMBER:
|
||||
case T::T_COLON:
|
||||
return [
|
||||
'type' => 'subexpression',
|
||||
'children' => [$left, $this->parseArrayIndexExpression()]
|
||||
];
|
||||
default:
|
||||
return $this->parseWildcardArray($left);
|
||||
}
|
||||
}
|
||||
|
||||
private function led_flatten(array $left)
|
||||
{
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => 'projection',
|
||||
'from' => 'array',
|
||||
'children' => [
|
||||
['type' => T::T_FLATTEN, 'children' => [$left]],
|
||||
$this->parseProjection(self::$bp[T::T_FLATTEN])
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_dot(array $left)
|
||||
{
|
||||
$this->next(self::$afterDot);
|
||||
|
||||
if ($this->token['type'] == T::T_STAR) {
|
||||
return $this->parseWildcardObject($left);
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => 'subexpression',
|
||||
'children' => [$left, $this->parseDot(self::$bp[T::T_DOT])]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_or(array $left)
|
||||
{
|
||||
$this->next();
|
||||
return [
|
||||
'type' => T::T_OR,
|
||||
'children' => [$left, $this->expr(self::$bp[T::T_OR])]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_and(array $left)
|
||||
{
|
||||
$this->next();
|
||||
return [
|
||||
'type' => T::T_AND,
|
||||
'children' => [$left, $this->expr(self::$bp[T::T_AND])]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_pipe(array $left)
|
||||
{
|
||||
$this->next();
|
||||
return [
|
||||
'type' => T::T_PIPE,
|
||||
'children' => [$left, $this->expr(self::$bp[T::T_PIPE])]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_lparen(array $left)
|
||||
{
|
||||
$args = [];
|
||||
$this->next();
|
||||
|
||||
while ($this->token['type'] != T::T_RPAREN) {
|
||||
$args[] = $this->expr(0);
|
||||
if ($this->token['type'] == T::T_COMMA) {
|
||||
$this->next();
|
||||
}
|
||||
}
|
||||
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => 'function',
|
||||
'value' => $left['value'],
|
||||
'children' => $args
|
||||
];
|
||||
}
|
||||
|
||||
private function led_filter(array $left)
|
||||
{
|
||||
$this->next();
|
||||
$expression = $this->expr();
|
||||
if ($this->token['type'] != T::T_RBRACKET) {
|
||||
throw $this->syntax('Expected a closing rbracket for the filter');
|
||||
}
|
||||
|
||||
$this->next();
|
||||
$rhs = $this->parseProjection(self::$bp[T::T_FILTER]);
|
||||
|
||||
return [
|
||||
'type' => 'projection',
|
||||
'from' => 'array',
|
||||
'children' => [
|
||||
$left ?: self::$currentNode,
|
||||
[
|
||||
'type' => 'condition',
|
||||
'children' => [$expression, $rhs]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private function led_comparator(array $left)
|
||||
{
|
||||
$token = $this->token;
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => T::T_COMPARATOR,
|
||||
'value' => $token['value'],
|
||||
'children' => [$left, $this->expr(self::$bp[T::T_COMPARATOR])]
|
||||
];
|
||||
}
|
||||
|
||||
private function parseProjection($bp)
|
||||
{
|
||||
$type = $this->token['type'];
|
||||
if (self::$bp[$type] < 10) {
|
||||
return self::$currentNode;
|
||||
} elseif ($type == T::T_DOT) {
|
||||
$this->next(self::$afterDot);
|
||||
return $this->parseDot($bp);
|
||||
} elseif ($type == T::T_LBRACKET || $type == T::T_FILTER) {
|
||||
return $this->expr($bp);
|
||||
}
|
||||
|
||||
throw $this->syntax('Syntax error after projection');
|
||||
}
|
||||
|
||||
private function parseDot($bp)
|
||||
{
|
||||
if ($this->token['type'] == T::T_LBRACKET) {
|
||||
$this->next();
|
||||
return $this->parseMultiSelectList();
|
||||
}
|
||||
|
||||
return $this->expr($bp);
|
||||
}
|
||||
|
||||
private function parseKeyValuePair()
|
||||
{
|
||||
static $validColon = [T::T_COLON => true];
|
||||
$key = $this->token['value'];
|
||||
$this->next($validColon);
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => 'key_val_pair',
|
||||
'value' => $key,
|
||||
'children' => [$this->expr()]
|
||||
];
|
||||
}
|
||||
|
||||
private function parseWildcardObject(array $left = null)
|
||||
{
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => 'projection',
|
||||
'from' => 'object',
|
||||
'children' => [
|
||||
$left ?: self::$currentNode,
|
||||
$this->parseProjection(self::$bp[T::T_STAR])
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private function parseWildcardArray(array $left = null)
|
||||
{
|
||||
static $getRbracket = [T::T_RBRACKET => true];
|
||||
$this->next($getRbracket);
|
||||
$this->next();
|
||||
|
||||
return [
|
||||
'type' => 'projection',
|
||||
'from' => 'array',
|
||||
'children' => [
|
||||
$left ?: self::$currentNode,
|
||||
$this->parseProjection(self::$bp[T::T_STAR])
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an array index expression (e.g., [0], [1:2:3]
|
||||
*/
|
||||
private function parseArrayIndexExpression()
|
||||
{
|
||||
static $matchNext = [
|
||||
T::T_NUMBER => true,
|
||||
T::T_COLON => true,
|
||||
T::T_RBRACKET => true
|
||||
];
|
||||
|
||||
$pos = 0;
|
||||
$parts = [null, null, null];
|
||||
$expected = $matchNext;
|
||||
|
||||
do {
|
||||
if ($this->token['type'] == T::T_COLON) {
|
||||
$pos++;
|
||||
$expected = $matchNext;
|
||||
} elseif ($this->token['type'] == T::T_NUMBER) {
|
||||
$parts[$pos] = $this->token['value'];
|
||||
$expected = [T::T_COLON => true, T::T_RBRACKET => true];
|
||||
}
|
||||
$this->next($expected);
|
||||
} while ($this->token['type'] != T::T_RBRACKET);
|
||||
|
||||
// Consume the closing bracket
|
||||
$this->next();
|
||||
|
||||
if ($pos === 0) {
|
||||
// No colons were found so this is a simple index extraction
|
||||
return ['type' => 'index', 'value' => $parts[0]];
|
||||
}
|
||||
|
||||
if ($pos > 2) {
|
||||
throw $this->syntax('Invalid array slice syntax: too many colons');
|
||||
}
|
||||
|
||||
// Sliced array from start (e.g., [2:])
|
||||
return [
|
||||
'type' => 'projection',
|
||||
'from' => 'array',
|
||||
'children' => [
|
||||
['type' => 'slice', 'value' => $parts],
|
||||
$this->parseProjection(self::$bp[T::T_STAR])
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private function parseMultiSelectList()
|
||||
{
|
||||
$nodes = [];
|
||||
|
||||
do {
|
||||
$nodes[] = $this->expr();
|
||||
if ($this->token['type'] == T::T_COMMA) {
|
||||
$this->next();
|
||||
$this->assertNotToken(T::T_RBRACKET);
|
||||
}
|
||||
} while ($this->token['type'] !== T::T_RBRACKET);
|
||||
$this->next();
|
||||
|
||||
return ['type' => 'multi_select_list', 'children' => $nodes];
|
||||
}
|
||||
|
||||
private function syntax($msg)
|
||||
{
|
||||
return new SyntaxErrorException($msg, $this->token, $this->expression);
|
||||
}
|
||||
|
||||
private function lookahead()
|
||||
{
|
||||
return (!isset($this->tokens[$this->tpos + 1]))
|
||||
? T::T_EOF
|
||||
: $this->tokens[$this->tpos + 1]['type'];
|
||||
}
|
||||
|
||||
private function next(array $match = null)
|
||||
{
|
||||
if (!isset($this->tokens[$this->tpos + 1])) {
|
||||
$this->token = self::$nullToken;
|
||||
} else {
|
||||
$this->token = $this->tokens[++$this->tpos];
|
||||
}
|
||||
|
||||
if ($match && !isset($match[$this->token['type']])) {
|
||||
throw $this->syntax($match);
|
||||
}
|
||||
}
|
||||
|
||||
private function assertNotToken($type)
|
||||
{
|
||||
if ($this->token['type'] == $type) {
|
||||
throw $this->syntax("Token {$this->tpos} not allowed to be $type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Handles undefined tokens without paying the cost of validation
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
$prefix = substr($method, 0, 4);
|
||||
if ($prefix == 'nud_' || $prefix == 'led_') {
|
||||
$token = substr($method, 4);
|
||||
$message = "Unexpected \"$token\" token ($method). Expected one of"
|
||||
. " the following tokens: "
|
||||
. implode(', ', array_map(function ($i) {
|
||||
return '"' . substr($i, 4) . '"';
|
||||
}, array_filter(
|
||||
get_class_methods($this),
|
||||
function ($i) use ($prefix) {
|
||||
return strpos($i, $prefix) === 0;
|
||||
}
|
||||
)));
|
||||
throw $this->syntax($message);
|
||||
}
|
||||
|
||||
throw new \BadMethodCallException("Call to undefined method $method");
|
||||
}
|
||||
}
|
36
vendor/mtdowling/jmespath.php/src/SyntaxErrorException.php
vendored
Normal file
36
vendor/mtdowling/jmespath.php/src/SyntaxErrorException.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Syntax errors raise this exception that gives context
|
||||
*/
|
||||
class SyntaxErrorException extends \InvalidArgumentException
|
||||
{
|
||||
/**
|
||||
* @param string $expectedTypesOrMessage Expected array of tokens or message
|
||||
* @param array $token Current token
|
||||
* @param string $expression Expression input
|
||||
*/
|
||||
public function __construct(
|
||||
$expectedTypesOrMessage,
|
||||
array $token,
|
||||
$expression
|
||||
) {
|
||||
$message = "Syntax error at character {$token['pos']}\n"
|
||||
. $expression . "\n" . str_repeat(' ', $token['pos']) . "^\n";
|
||||
$message .= !is_array($expectedTypesOrMessage)
|
||||
? $expectedTypesOrMessage
|
||||
: $this->createTokenMessage($token, $expectedTypesOrMessage);
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
private function createTokenMessage(array $token, array $valid)
|
||||
{
|
||||
return sprintf(
|
||||
'Expected one of the following: %s; found %s "%s"',
|
||||
implode(', ', array_keys($valid)),
|
||||
$token['type'],
|
||||
$token['value']
|
||||
);
|
||||
}
|
||||
}
|
419
vendor/mtdowling/jmespath.php/src/TreeCompiler.php
vendored
Normal file
419
vendor/mtdowling/jmespath.php/src/TreeCompiler.php
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Tree visitor used to compile JMESPath expressions into native PHP code.
|
||||
*/
|
||||
class TreeCompiler
|
||||
{
|
||||
private $indentation;
|
||||
private $source;
|
||||
private $vars;
|
||||
|
||||
/**
|
||||
* @param array $ast AST to compile.
|
||||
* @param string $fnName The name of the function to generate.
|
||||
* @param string $expr Expression being compiled.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function visit(array $ast, $fnName, $expr)
|
||||
{
|
||||
$this->vars = [];
|
||||
$this->source = $this->indentation = '';
|
||||
$this->write("<?php\n")
|
||||
->write('use JmesPath\\TreeInterpreter as Ti;')
|
||||
->write('use JmesPath\\FnDispatcher as Fn;')
|
||||
->write('use JmesPath\\Utils;')
|
||||
->write('')
|
||||
->write('function %s(Ti $interpreter, $value) {', $fnName)
|
||||
->indent()
|
||||
->dispatch($ast)
|
||||
->write('')
|
||||
->write('return $value;')
|
||||
->outdent()
|
||||
->write('}');
|
||||
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return mixed
|
||||
*/
|
||||
private function dispatch(array $node)
|
||||
{
|
||||
return $this->{"visit_{$node['type']}"}($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a monotonically incrementing unique variable name by prefix.
|
||||
*
|
||||
* @param string $prefix Variable name prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function makeVar($prefix)
|
||||
{
|
||||
if (!isset($this->vars[$prefix])) {
|
||||
$this->vars[$prefix] = 0;
|
||||
return '$' . $prefix;
|
||||
}
|
||||
|
||||
return '$' . $prefix . ++$this->vars[$prefix];
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given line of source code. Pass positional arguments to write
|
||||
* that match the format of sprintf.
|
||||
*
|
||||
* @param string $str String to write
|
||||
* @return $this
|
||||
*/
|
||||
private function write($str)
|
||||
{
|
||||
$this->source .= $this->indentation;
|
||||
if (func_num_args() == 1) {
|
||||
$this->source .= $str . "\n";
|
||||
return $this;
|
||||
}
|
||||
$this->source .= vsprintf($str, array_slice(func_get_args(), 1)) . "\n";
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the indentation level of code being written
|
||||
* @return $this
|
||||
*/
|
||||
private function outdent()
|
||||
{
|
||||
$this->indentation = substr($this->indentation, 0, -4);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the indentation level of code being written
|
||||
* @return $this
|
||||
*/
|
||||
private function indent()
|
||||
{
|
||||
$this->indentation .= ' ';
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function visit_or(array $node)
|
||||
{
|
||||
$a = $this->makeVar('beforeOr');
|
||||
return $this
|
||||
->write('%s = $value;', $a)
|
||||
->dispatch($node['children'][0])
|
||||
->write('if (!$value && $value !== "0" && $value !== 0) {')
|
||||
->indent()
|
||||
->write('$value = %s;', $a)
|
||||
->dispatch($node['children'][1])
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_and(array $node)
|
||||
{
|
||||
$a = $this->makeVar('beforeAnd');
|
||||
return $this
|
||||
->write('%s = $value;', $a)
|
||||
->dispatch($node['children'][0])
|
||||
->write('if ($value || $value === "0" || $value === 0) {')
|
||||
->indent()
|
||||
->write('$value = %s;', $a)
|
||||
->dispatch($node['children'][1])
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_not(array $node)
|
||||
{
|
||||
return $this
|
||||
->write('// Visiting not node')
|
||||
->dispatch($node['children'][0])
|
||||
->write('// Applying boolean not to result of not node')
|
||||
->write('$value = !Utils::isTruthy($value);');
|
||||
}
|
||||
|
||||
private function visit_subexpression(array $node)
|
||||
{
|
||||
return $this
|
||||
->dispatch($node['children'][0])
|
||||
->write('if ($value !== null) {')
|
||||
->indent()
|
||||
->dispatch($node['children'][1])
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_field(array $node)
|
||||
{
|
||||
$arr = '$value[' . var_export($node['value'], true) . ']';
|
||||
$obj = '$value->{' . var_export($node['value'], true) . '}';
|
||||
$this->write('if (is_array($value) || $value instanceof \\ArrayAccess) {')
|
||||
->indent()
|
||||
->write('$value = isset(%s) ? %s : null;', $arr, $arr)
|
||||
->outdent()
|
||||
->write('} elseif ($value instanceof \\stdClass) {')
|
||||
->indent()
|
||||
->write('$value = isset(%s) ? %s : null;', $obj, $obj)
|
||||
->outdent()
|
||||
->write("} else {")
|
||||
->indent()
|
||||
->write('$value = null;')
|
||||
->outdent()
|
||||
->write("}");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function visit_index(array $node)
|
||||
{
|
||||
if ($node['value'] >= 0) {
|
||||
$check = '$value[' . $node['value'] . ']';
|
||||
return $this->write(
|
||||
'$value = (is_array($value) || $value instanceof \\ArrayAccess)'
|
||||
. ' && isset(%s) ? %s : null;',
|
||||
$check, $check
|
||||
);
|
||||
}
|
||||
|
||||
$a = $this->makeVar('count');
|
||||
return $this
|
||||
->write('if (is_array($value) || ($value instanceof \\ArrayAccess && $value instanceof \\Countable)) {')
|
||||
->indent()
|
||||
->write('%s = count($value) + %s;', $a, $node['value'])
|
||||
->write('$value = isset($value[%s]) ? $value[%s] : null;', $a, $a)
|
||||
->outdent()
|
||||
->write('} else {')
|
||||
->indent()
|
||||
->write('$value = null;')
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_literal(array $node)
|
||||
{
|
||||
return $this->write('$value = %s;', var_export($node['value'], true));
|
||||
}
|
||||
|
||||
private function visit_pipe(array $node)
|
||||
{
|
||||
return $this
|
||||
->dispatch($node['children'][0])
|
||||
->dispatch($node['children'][1]);
|
||||
}
|
||||
|
||||
private function visit_multi_select_list(array $node)
|
||||
{
|
||||
return $this->visit_multi_select_hash($node);
|
||||
}
|
||||
|
||||
private function visit_multi_select_hash(array $node)
|
||||
{
|
||||
$listVal = $this->makeVar('list');
|
||||
$value = $this->makeVar('prev');
|
||||
$this->write('if ($value !== null) {')
|
||||
->indent()
|
||||
->write('%s = [];', $listVal)
|
||||
->write('%s = $value;', $value);
|
||||
|
||||
$first = true;
|
||||
foreach ($node['children'] as $child) {
|
||||
if (!$first) {
|
||||
$this->write('$value = %s;', $value);
|
||||
}
|
||||
$first = false;
|
||||
if ($node['type'] == 'multi_select_hash') {
|
||||
$this->dispatch($child['children'][0]);
|
||||
$key = var_export($child['value'], true);
|
||||
$this->write('%s[%s] = $value;', $listVal, $key);
|
||||
} else {
|
||||
$this->dispatch($child);
|
||||
$this->write('%s[] = $value;', $listVal);
|
||||
}
|
||||
}
|
||||
|
||||
return $this
|
||||
->write('$value = %s;', $listVal)
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_function(array $node)
|
||||
{
|
||||
$value = $this->makeVar('val');
|
||||
$args = $this->makeVar('args');
|
||||
$this->write('%s = $value;', $value)
|
||||
->write('%s = [];', $args);
|
||||
|
||||
foreach ($node['children'] as $arg) {
|
||||
$this->dispatch($arg);
|
||||
$this->write('%s[] = $value;', $args)
|
||||
->write('$value = %s;', $value);
|
||||
}
|
||||
|
||||
return $this->write(
|
||||
'$value = Fn::getInstance()->__invoke("%s", %s);',
|
||||
$node['value'], $args
|
||||
);
|
||||
}
|
||||
|
||||
private function visit_slice(array $node)
|
||||
{
|
||||
return $this
|
||||
->write('$value = !is_string($value) && !Utils::isArray($value)')
|
||||
->write(' ? null : Utils::slice($value, %s, %s, %s);',
|
||||
var_export($node['value'][0], true),
|
||||
var_export($node['value'][1], true),
|
||||
var_export($node['value'][2], true)
|
||||
);
|
||||
}
|
||||
|
||||
private function visit_current(array $node)
|
||||
{
|
||||
return $this->write('// Visiting current node (no-op)');
|
||||
}
|
||||
|
||||
private function visit_expref(array $node)
|
||||
{
|
||||
$child = var_export($node['children'][0], true);
|
||||
return $this->write('$value = function ($value) use ($interpreter) {')
|
||||
->indent()
|
||||
->write('return $interpreter->visit(%s, $value);', $child)
|
||||
->outdent()
|
||||
->write('};');
|
||||
}
|
||||
|
||||
private function visit_flatten(array $node)
|
||||
{
|
||||
$this->dispatch($node['children'][0]);
|
||||
$merged = $this->makeVar('merged');
|
||||
$val = $this->makeVar('val');
|
||||
|
||||
$this
|
||||
->write('// Visiting merge node')
|
||||
->write('if (!Utils::isArray($value)) {')
|
||||
->indent()
|
||||
->write('$value = null;')
|
||||
->outdent()
|
||||
->write('} else {')
|
||||
->indent()
|
||||
->write('%s = [];', $merged)
|
||||
->write('foreach ($value as %s) {', $val)
|
||||
->indent()
|
||||
->write('if (is_array(%s) && isset(%s[0])) {', $val, $val)
|
||||
->indent()
|
||||
->write('%s = array_merge(%s, %s);', $merged, $merged, $val)
|
||||
->outdent()
|
||||
->write('} elseif (%s !== []) {', $val)
|
||||
->indent()
|
||||
->write('%s[] = %s;', $merged, $val)
|
||||
->outdent()
|
||||
->write('}')
|
||||
->outdent()
|
||||
->write('}')
|
||||
->write('$value = %s;', $merged)
|
||||
->outdent()
|
||||
->write('}');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function visit_projection(array $node)
|
||||
{
|
||||
$val = $this->makeVar('val');
|
||||
$collected = $this->makeVar('collected');
|
||||
$this->write('// Visiting projection node')
|
||||
->dispatch($node['children'][0])
|
||||
->write('');
|
||||
|
||||
if (!isset($node['from'])) {
|
||||
$this->write('if (!is_array($value) || !($value instanceof \stdClass)) { $value = null; }');
|
||||
} elseif ($node['from'] == 'object') {
|
||||
$this->write('if (!Utils::isObject($value)) { $value = null; }');
|
||||
} elseif ($node['from'] == 'array') {
|
||||
$this->write('if (!Utils::isArray($value)) { $value = null; }');
|
||||
}
|
||||
|
||||
$this->write('if ($value !== null) {')
|
||||
->indent()
|
||||
->write('%s = [];', $collected)
|
||||
->write('foreach ((array) $value as %s) {', $val)
|
||||
->indent()
|
||||
->write('$value = %s;', $val)
|
||||
->dispatch($node['children'][1])
|
||||
->write('if ($value !== null) {')
|
||||
->indent()
|
||||
->write('%s[] = $value;', $collected)
|
||||
->outdent()
|
||||
->write('}')
|
||||
->outdent()
|
||||
->write('}')
|
||||
->write('$value = %s;', $collected)
|
||||
->outdent()
|
||||
->write('}');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function visit_condition(array $node)
|
||||
{
|
||||
$value = $this->makeVar('beforeCondition');
|
||||
return $this
|
||||
->write('%s = $value;', $value)
|
||||
->write('// Visiting condition node')
|
||||
->dispatch($node['children'][0])
|
||||
->write('// Checking result of condition node')
|
||||
->write('if (Utils::isTruthy($value)) {')
|
||||
->indent()
|
||||
->write('$value = %s;', $value)
|
||||
->dispatch($node['children'][1])
|
||||
->outdent()
|
||||
->write('} else {')
|
||||
->indent()
|
||||
->write('$value = null;')
|
||||
->outdent()
|
||||
->write('}');
|
||||
}
|
||||
|
||||
private function visit_comparator(array $node)
|
||||
{
|
||||
$value = $this->makeVar('val');
|
||||
$a = $this->makeVar('left');
|
||||
$b = $this->makeVar('right');
|
||||
|
||||
$this
|
||||
->write('// Visiting comparator node')
|
||||
->write('%s = $value;', $value)
|
||||
->dispatch($node['children'][0])
|
||||
->write('%s = $value;', $a)
|
||||
->write('$value = %s;', $value)
|
||||
->dispatch($node['children'][1])
|
||||
->write('%s = $value;', $b);
|
||||
|
||||
if ($node['value'] == '==') {
|
||||
$this->write('$value = Utils::isEqual(%s, %s);', $a, $b);
|
||||
} elseif ($node['value'] == '!=') {
|
||||
$this->write('$value = !Utils::isEqual(%s, %s);', $a, $b);
|
||||
} else {
|
||||
$this->write(
|
||||
'$value = is_int(%s) && is_int(%s) && %s %s %s;',
|
||||
$a, $b, $a, $node['value'], $b
|
||||
);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
public function __call($method, $args)
|
||||
{
|
||||
throw new \RuntimeException(
|
||||
sprintf('Invalid node encountered: %s', json_encode($args[0]))
|
||||
);
|
||||
}
|
||||
}
|
235
vendor/mtdowling/jmespath.php/src/TreeInterpreter.php
vendored
Normal file
235
vendor/mtdowling/jmespath.php/src/TreeInterpreter.php
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
/**
|
||||
* Tree visitor used to evaluates JMESPath AST expressions.
|
||||
*/
|
||||
class TreeInterpreter
|
||||
{
|
||||
/** @var callable */
|
||||
private $fnDispatcher;
|
||||
|
||||
/**
|
||||
* @param callable $fnDispatcher Function dispatching function that accepts
|
||||
* a function name argument and an array of
|
||||
* function arguments and returns the result.
|
||||
*/
|
||||
public function __construct(callable $fnDispatcher = null)
|
||||
{
|
||||
$this->fnDispatcher = $fnDispatcher ?: FnDispatcher::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits each node in a JMESPath AST and returns the evaluated result.
|
||||
*
|
||||
* @param array $node JMESPath AST node
|
||||
* @param mixed $data Data to evaluate
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function visit(array $node, $data)
|
||||
{
|
||||
return $this->dispatch($node, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively traverses an AST using depth-first, pre-order traversal.
|
||||
* The evaluation logic for each node type is embedded into a large switch
|
||||
* statement to avoid the cost of "double dispatch".
|
||||
* @return mixed
|
||||
*/
|
||||
private function dispatch(array $node, $value)
|
||||
{
|
||||
$dispatcher = $this->fnDispatcher;
|
||||
|
||||
switch ($node['type']) {
|
||||
|
||||
case 'field':
|
||||
if (is_array($value) || $value instanceof \ArrayAccess) {
|
||||
return isset($value[$node['value']]) ? $value[$node['value']] : null;
|
||||
} elseif ($value instanceof \stdClass) {
|
||||
return isset($value->{$node['value']}) ? $value->{$node['value']} : null;
|
||||
}
|
||||
return null;
|
||||
|
||||
case 'subexpression':
|
||||
return $this->dispatch(
|
||||
$node['children'][1],
|
||||
$this->dispatch($node['children'][0], $value)
|
||||
);
|
||||
|
||||
case 'index':
|
||||
if (!Utils::isArray($value)) {
|
||||
return null;
|
||||
}
|
||||
$idx = $node['value'] >= 0
|
||||
? $node['value']
|
||||
: $node['value'] + count($value);
|
||||
return isset($value[$idx]) ? $value[$idx] : null;
|
||||
|
||||
case 'projection':
|
||||
$left = $this->dispatch($node['children'][0], $value);
|
||||
switch ($node['from']) {
|
||||
case 'object':
|
||||
if (!Utils::isObject($left)) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case 'array':
|
||||
if (!Utils::isArray($left)) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!is_array($left) || !($left instanceof \stdClass)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$collected = [];
|
||||
foreach ((array) $left as $val) {
|
||||
$result = $this->dispatch($node['children'][1], $val);
|
||||
if ($result !== null) {
|
||||
$collected[] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $collected;
|
||||
|
||||
case 'flatten':
|
||||
static $skipElement = [];
|
||||
$value = $this->dispatch($node['children'][0], $value);
|
||||
|
||||
if (!Utils::isArray($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$merged = [];
|
||||
foreach ($value as $values) {
|
||||
// Only merge up arrays lists and not hashes
|
||||
if (is_array($values) && isset($values[0])) {
|
||||
$merged = array_merge($merged, $values);
|
||||
} elseif ($values !== $skipElement) {
|
||||
$merged[] = $values;
|
||||
}
|
||||
}
|
||||
|
||||
return $merged;
|
||||
|
||||
case 'literal':
|
||||
return $node['value'];
|
||||
|
||||
case 'current':
|
||||
return $value;
|
||||
|
||||
case 'or':
|
||||
$result = $this->dispatch($node['children'][0], $value);
|
||||
return Utils::isTruthy($result)
|
||||
? $result
|
||||
: $this->dispatch($node['children'][1], $value);
|
||||
|
||||
case 'and':
|
||||
$result = $this->dispatch($node['children'][0], $value);
|
||||
return Utils::isTruthy($result)
|
||||
? $this->dispatch($node['children'][1], $value)
|
||||
: $result;
|
||||
|
||||
case 'not':
|
||||
return !Utils::isTruthy(
|
||||
$this->dispatch($node['children'][0], $value)
|
||||
);
|
||||
|
||||
case 'pipe':
|
||||
return $this->dispatch(
|
||||
$node['children'][1],
|
||||
$this->dispatch($node['children'][0], $value)
|
||||
);
|
||||
|
||||
case 'multi_select_list':
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$collected = [];
|
||||
foreach ($node['children'] as $node) {
|
||||
$collected[] = $this->dispatch($node, $value);
|
||||
}
|
||||
|
||||
return $collected;
|
||||
|
||||
case 'multi_select_hash':
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$collected = [];
|
||||
foreach ($node['children'] as $node) {
|
||||
$collected[$node['value']] = $this->dispatch(
|
||||
$node['children'][0],
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
return $collected;
|
||||
|
||||
case 'comparator':
|
||||
$left = $this->dispatch($node['children'][0], $value);
|
||||
$right = $this->dispatch($node['children'][1], $value);
|
||||
if ($node['value'] == '==') {
|
||||
return Utils::isEqual($left, $right);
|
||||
} elseif ($node['value'] == '!=') {
|
||||
return !Utils::isEqual($left, $right);
|
||||
} else {
|
||||
return self::relativeCmp($left, $right, $node['value']);
|
||||
}
|
||||
|
||||
case 'condition':
|
||||
return Utils::isTruthy($this->dispatch($node['children'][0], $value))
|
||||
? $this->dispatch($node['children'][1], $value)
|
||||
: null;
|
||||
|
||||
case 'function':
|
||||
$args = [];
|
||||
foreach ($node['children'] as $arg) {
|
||||
$args[] = $this->dispatch($arg, $value);
|
||||
}
|
||||
return $dispatcher($node['value'], $args);
|
||||
|
||||
case 'slice':
|
||||
return is_string($value) || Utils::isArray($value)
|
||||
? Utils::slice(
|
||||
$value,
|
||||
$node['value'][0],
|
||||
$node['value'][1],
|
||||
$node['value'][2]
|
||||
) : null;
|
||||
|
||||
case 'expref':
|
||||
$apply = $node['children'][0];
|
||||
return function ($value) use ($apply) {
|
||||
return $this->visit($apply, $value);
|
||||
};
|
||||
|
||||
default:
|
||||
throw new \RuntimeException("Unknown node type: {$node['type']}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private static function relativeCmp($left, $right, $cmp)
|
||||
{
|
||||
if (!is_int($left) || !is_int($right)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($cmp) {
|
||||
case '>': return $left > $right;
|
||||
case '>=': return $left >= $right;
|
||||
case '<': return $left < $right;
|
||||
case '<=': return $left <= $right;
|
||||
default: throw new \RuntimeException("Invalid comparison: $cmp");
|
||||
}
|
||||
}
|
||||
}
|
229
vendor/mtdowling/jmespath.php/src/Utils.php
vendored
Normal file
229
vendor/mtdowling/jmespath.php/src/Utils.php
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
namespace JmesPath;
|
||||
|
||||
class Utils
|
||||
{
|
||||
static $typeMap = [
|
||||
'boolean' => 'boolean',
|
||||
'string' => 'string',
|
||||
'NULL' => 'null',
|
||||
'double' => 'number',
|
||||
'float' => 'number',
|
||||
'integer' => 'number'
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns true if the value is truthy
|
||||
*
|
||||
* @param mixed $value Value to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isTruthy($value)
|
||||
{
|
||||
if (!$value) {
|
||||
return $value === 0 || $value === '0';
|
||||
} elseif ($value instanceof \stdClass) {
|
||||
return (bool) get_object_vars($value);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JMESPath type equivalent of a PHP variable.
|
||||
*
|
||||
* @param mixed $arg PHP variable
|
||||
* @return string Returns the JSON data type
|
||||
* @throws \InvalidArgumentException when an unknown type is given.
|
||||
*/
|
||||
public static function type($arg)
|
||||
{
|
||||
$type = gettype($arg);
|
||||
if (isset(self::$typeMap[$type])) {
|
||||
return self::$typeMap[$type];
|
||||
} elseif ($type === 'array') {
|
||||
if (empty($arg)) {
|
||||
return 'array';
|
||||
}
|
||||
reset($arg);
|
||||
return key($arg) === 0 ? 'array' : 'object';
|
||||
} elseif ($arg instanceof \stdClass) {
|
||||
return 'object';
|
||||
} elseif ($arg instanceof \Closure) {
|
||||
return 'expression';
|
||||
} elseif ($arg instanceof \ArrayAccess
|
||||
&& $arg instanceof \Countable
|
||||
) {
|
||||
return count($arg) == 0 || $arg->offsetExists(0)
|
||||
? 'array'
|
||||
: 'object';
|
||||
} elseif (method_exists($arg, '__toString')) {
|
||||
return 'string';
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(
|
||||
'Unable to determine JMESPath type from ' . get_class($arg)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the provided value is a JMESPath compatible object.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isObject($value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return !$value || array_keys($value)[0] !== 0;
|
||||
}
|
||||
|
||||
// Handle array-like values. Must be empty or offset 0 does not exist
|
||||
return $value instanceof \Countable && $value instanceof \ArrayAccess
|
||||
? count($value) == 0 || !$value->offsetExists(0)
|
||||
: $value instanceof \stdClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the provided value is a JMESPath compatible array.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isArray($value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return !$value || array_keys($value)[0] === 0;
|
||||
}
|
||||
|
||||
// Handle array-like values. Must be empty or offset 0 exists.
|
||||
return $value instanceof \Countable && $value instanceof \ArrayAccess
|
||||
? count($value) == 0 || $value->offsetExists(0)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON aware value comparison function.
|
||||
*
|
||||
* @param mixed $a First value to compare
|
||||
* @param mixed $b Second value to compare
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isEqual($a, $b)
|
||||
{
|
||||
if ($a === $b) {
|
||||
return true;
|
||||
} elseif ($a instanceof \stdClass) {
|
||||
return self::isEqual((array) $a, $b);
|
||||
} elseif ($b instanceof \stdClass) {
|
||||
return self::isEqual($a, (array) $b);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JMESPath requires a stable sorting algorithm, so here we'll implement
|
||||
* a simple Schwartzian transform that uses array index positions as tie
|
||||
* breakers.
|
||||
*
|
||||
* @param array $data List or map of data to sort
|
||||
* @param callable $sortFn Callable used to sort values
|
||||
*
|
||||
* @return array Returns the sorted array
|
||||
* @link http://en.wikipedia.org/wiki/Schwartzian_transform
|
||||
*/
|
||||
public static function stableSort(array $data, callable $sortFn)
|
||||
{
|
||||
// Decorate each item by creating an array of [value, index]
|
||||
array_walk($data, function (&$v, $k) { $v = [$v, $k]; });
|
||||
// Sort by the sort function and use the index as a tie-breaker
|
||||
uasort($data, function ($a, $b) use ($sortFn) {
|
||||
return $sortFn($a[0], $b[0]) ?: ($a[1] < $b[1] ? -1 : 1);
|
||||
});
|
||||
|
||||
// Undecorate each item and return the resulting sorted array
|
||||
return array_map(function ($v) { return $v[0]; }, array_values($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Python-style slice of a string or array.
|
||||
*
|
||||
* @param array|string $value Value to slice
|
||||
* @param int|null $start Starting position
|
||||
* @param int|null $stop Stop position
|
||||
* @param int $step Step (1, 2, -1, -2, etc.)
|
||||
*
|
||||
* @return array|string
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function slice($value, $start = null, $stop = null, $step = 1)
|
||||
{
|
||||
if (!is_array($value) && !is_string($value)) {
|
||||
throw new \InvalidArgumentException('Expects string or array');
|
||||
}
|
||||
|
||||
return self::sliceIndices($value, $start, $stop, $step);
|
||||
}
|
||||
|
||||
private static function adjustEndpoint($length, $endpoint, $step)
|
||||
{
|
||||
if ($endpoint < 0) {
|
||||
$endpoint += $length;
|
||||
if ($endpoint < 0) {
|
||||
$endpoint = $step < 0 ? -1 : 0;
|
||||
}
|
||||
} elseif ($endpoint >= $length) {
|
||||
$endpoint = $step < 0 ? $length - 1 : $length;
|
||||
}
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
private static function adjustSlice($length, $start, $stop, $step)
|
||||
{
|
||||
if ($step === null) {
|
||||
$step = 1;
|
||||
} elseif ($step === 0) {
|
||||
throw new \RuntimeException('step cannot be 0');
|
||||
}
|
||||
|
||||
if ($start === null) {
|
||||
$start = $step < 0 ? $length - 1 : 0;
|
||||
} else {
|
||||
$start = self::adjustEndpoint($length, $start, $step);
|
||||
}
|
||||
|
||||
if ($stop === null) {
|
||||
$stop = $step < 0 ? -1 : $length;
|
||||
} else {
|
||||
$stop = self::adjustEndpoint($length, $stop, $step);
|
||||
}
|
||||
|
||||
return [$start, $stop, $step];
|
||||
}
|
||||
|
||||
private static function sliceIndices($subject, $start, $stop, $step)
|
||||
{
|
||||
$type = gettype($subject);
|
||||
$len = $type == 'string' ? strlen($subject) : count($subject);
|
||||
list($start, $stop, $step) = self::adjustSlice($len, $start, $stop, $step);
|
||||
|
||||
$result = [];
|
||||
if ($step > 0) {
|
||||
for ($i = $start; $i < $stop; $i += $step) {
|
||||
$result[] = $subject[$i];
|
||||
}
|
||||
} else {
|
||||
for ($i = $start; $i > $stop; $i += $step) {
|
||||
$result[] = $subject[$i];
|
||||
}
|
||||
}
|
||||
|
||||
return $type == 'string' ? implode($result, '') : $result;
|
||||
}
|
||||
}
|
136
vendor/mtdowling/jmespath.php/tests/ComplianceTest.php
vendored
Normal file
136
vendor/mtdowling/jmespath.php/tests/ComplianceTest.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\AstRuntime;
|
||||
use JmesPath\CompilerRuntime;
|
||||
use JmesPath\SyntaxErrorException;
|
||||
|
||||
class ComplianceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private static $path;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
self::$path = __DIR__ . '/../../compiled';
|
||||
array_map('unlink', glob(self::$path . '/jmespath_*.php'));
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
array_map('unlink', glob(self::$path . '/jmespath_*.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider complianceProvider
|
||||
*/
|
||||
public function testPassesCompliance(
|
||||
$data,
|
||||
$expression,
|
||||
$result,
|
||||
$error,
|
||||
$file,
|
||||
$suite,
|
||||
$case,
|
||||
$compiled,
|
||||
$asAssoc
|
||||
) {
|
||||
$evalResult = null;
|
||||
$failed = false;
|
||||
$failureMsg = '';
|
||||
$failure = '';
|
||||
$compiledStr = '';
|
||||
|
||||
try {
|
||||
if ($compiled) {
|
||||
$compiledStr = \JmesPath\Env::COMPILE_DIR . '=on ';
|
||||
$runtime = new CompilerRuntime(self::$path);
|
||||
} else {
|
||||
$runtime = new AstRuntime();
|
||||
}
|
||||
$evalResult = $runtime($expression, $data);
|
||||
} catch (\Exception $e) {
|
||||
$failed = $e instanceof SyntaxErrorException ? 'syntax' : 'runtime';
|
||||
$failureMsg = sprintf(
|
||||
'%s (%s line %d)',
|
||||
$e->getMessage(),
|
||||
$e->getFile(),
|
||||
$e->getLine()
|
||||
);
|
||||
}
|
||||
|
||||
$file = __DIR__ . '/compliance/' . $file . '.json';
|
||||
$failure .= "\n{$compiledStr}php bin/jp.php --file {$file} --suite {$suite} --case {$case}\n\n"
|
||||
. "Expected: " . $this->prettyJson($result) . "\n\n";
|
||||
$failure .= 'Associative? ' . var_export($asAssoc, true) . "\n\n";
|
||||
|
||||
if (!$error && $failed) {
|
||||
$this->fail("Should not have failed\n{$failure}=> {$failed} {$failureMsg}");
|
||||
} elseif ($error && !$failed) {
|
||||
$this->fail("Should have failed\n{$failure}");
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
$this->convertAssoc($result),
|
||||
$this->convertAssoc($evalResult),
|
||||
$failure
|
||||
);
|
||||
}
|
||||
|
||||
public function complianceProvider()
|
||||
{
|
||||
$cases = [];
|
||||
|
||||
$files = array_map(function ($f) {
|
||||
return basename($f, '.json');
|
||||
}, glob(__DIR__ . '/compliance/*.json'));
|
||||
|
||||
foreach ($files as $name) {
|
||||
$contents = file_get_contents(__DIR__ . "/compliance/{$name}.json");
|
||||
foreach ([true, false] as $asAssoc) {
|
||||
$json = json_decode($contents, true);
|
||||
$jsonObj = json_decode($contents);
|
||||
foreach ($json as $suiteNumber => $suite) {
|
||||
$given = $asAssoc ? $suite['given'] : $jsonObj[$suiteNumber]->given;
|
||||
foreach ($suite['cases'] as $caseNumber => $case) {
|
||||
$caseData = [
|
||||
$given,
|
||||
$case['expression'],
|
||||
isset($case['result']) ? $case['result'] : null,
|
||||
isset($case['error']) ? $case['error'] : false,
|
||||
$name,
|
||||
$suiteNumber,
|
||||
$caseNumber,
|
||||
false,
|
||||
$asAssoc
|
||||
];
|
||||
$cases[] = $caseData;
|
||||
$caseData[7] = true;
|
||||
$cases[] = $caseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $cases;
|
||||
}
|
||||
|
||||
private function convertAssoc($data)
|
||||
{
|
||||
if ($data instanceof \stdClass) {
|
||||
return $this->convertAssoc((array) $data);
|
||||
} elseif (is_array($data)) {
|
||||
return array_map([$this, 'convertAssoc'], $data);
|
||||
} else {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
private function prettyJson($json)
|
||||
{
|
||||
if (defined('JSON_PRETTY_PRINT')) {
|
||||
return json_encode($json, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
return json_encode($json);
|
||||
}
|
||||
}
|
31
vendor/mtdowling/jmespath.php/tests/EnvTest.php
vendored
Normal file
31
vendor/mtdowling/jmespath.php/tests/EnvTest.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\Env;
|
||||
use JmesPath\CompilerRuntime;
|
||||
|
||||
class EnvTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSearchesInput()
|
||||
{
|
||||
$data = array('foo' => 123);
|
||||
$this->assertEquals(123, Env::search('foo', $data));
|
||||
$this->assertEquals(123, Env::search('foo', $data));
|
||||
}
|
||||
|
||||
public function testSearchesWithFunction()
|
||||
{
|
||||
$data = array('foo' => 123);
|
||||
$this->assertEquals(123, \JmesPath\search('foo', $data));
|
||||
}
|
||||
|
||||
public function testCleansCompileDir()
|
||||
{
|
||||
$dir = sys_get_temp_dir();
|
||||
$runtime = new CompilerRuntime($dir);
|
||||
$runtime('@ | @ | @[0][0][0]', []);
|
||||
$this->assertNotEmpty(glob($dir . '/jmespath_*.php'));
|
||||
$this->assertGreaterThan(0, Env::cleanCompileDir());
|
||||
$this->assertEmpty(glob($dir . '/jmespath_*.php'));
|
||||
}
|
||||
}
|
41
vendor/mtdowling/jmespath.php/tests/FnDispatcherTest.php
vendored
Normal file
41
vendor/mtdowling/jmespath.php/tests/FnDispatcherTest.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\FnDispatcher;
|
||||
|
||||
class FnDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConvertsToString()
|
||||
{
|
||||
$fn = new FnDispatcher();
|
||||
$this->assertEquals('foo', $fn('to_string', ['foo']));
|
||||
$this->assertEquals('1', $fn('to_string', [1]));
|
||||
$this->assertEquals('["foo"]', $fn('to_string', [['foo']]));
|
||||
$std = new \stdClass();
|
||||
$std->foo = 'bar';
|
||||
$this->assertEquals('{"foo":"bar"}', $fn('to_string', [$std]));
|
||||
$this->assertEquals('foo', $fn('to_string', [new _TestStringClass()]));
|
||||
$this->assertEquals('"foo"', $fn('to_string', [new _TestJsonStringClass()]));
|
||||
}
|
||||
}
|
||||
|
||||
class _TestStringClass
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'foo';
|
||||
}
|
||||
}
|
||||
|
||||
class _TestJsonStringClass implements \JsonSerializable
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'no!';
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return 'foo';
|
||||
}
|
||||
}
|
88
vendor/mtdowling/jmespath.php/tests/LexerTest.php
vendored
Normal file
88
vendor/mtdowling/jmespath.php/tests/LexerTest.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\Lexer;
|
||||
use JmesPath\SyntaxErrorException;
|
||||
|
||||
/**
|
||||
* @covers JmesPath\Lexer
|
||||
*/
|
||||
class LexerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function inputProvider()
|
||||
{
|
||||
return array(
|
||||
array('0', 'number'),
|
||||
array('1', 'number'),
|
||||
array('2', 'number'),
|
||||
array('3', 'number'),
|
||||
array('4', 'number'),
|
||||
array('5', 'number'),
|
||||
array('6', 'number'),
|
||||
array('7', 'number'),
|
||||
array('8', 'number'),
|
||||
array('9', 'number'),
|
||||
array('-1', 'number'),
|
||||
array('-1.5', 'number'),
|
||||
array('109.5', 'number'),
|
||||
array('.', 'dot'),
|
||||
array('{', 'lbrace'),
|
||||
array('}', 'rbrace'),
|
||||
array('[', 'lbracket'),
|
||||
array(']', 'rbracket'),
|
||||
array(':', 'colon'),
|
||||
array(',', 'comma'),
|
||||
array('||', 'or'),
|
||||
array('*', 'star'),
|
||||
array('foo', 'identifier'),
|
||||
array('"foo"', 'quoted_identifier'),
|
||||
array('`true`', 'literal'),
|
||||
array('`false`', 'literal'),
|
||||
array('`null`', 'literal'),
|
||||
array('`"true"`', 'literal')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider inputProvider
|
||||
*/
|
||||
public function testTokenizesInput($input, $type)
|
||||
{
|
||||
$l = new Lexer();
|
||||
$tokens = $l->tokenize($input);
|
||||
$this->assertEquals($tokens[0]['type'], $type);
|
||||
}
|
||||
|
||||
public function testTokenizesJsonLiterals()
|
||||
{
|
||||
$l = new Lexer();
|
||||
$tokens = $l->tokenize('`null`, `false`, `true`, `"abc"`, `"ab\\"c"`,'
|
||||
. '`0`, `0.45`, `-0.5`');
|
||||
$this->assertNull($tokens[0]['value']);
|
||||
$this->assertFalse($tokens[2]['value']);
|
||||
$this->assertTrue($tokens[4]['value']);
|
||||
$this->assertEquals('abc', $tokens[6]['value']);
|
||||
$this->assertEquals('ab"c', $tokens[8]['value']);
|
||||
$this->assertSame(0, $tokens[10]['value']);
|
||||
$this->assertSame(0.45, $tokens[12]['value']);
|
||||
$this->assertSame(-0.5, $tokens[14]['value']);
|
||||
}
|
||||
|
||||
public function testTokenizesJsonNumbers()
|
||||
{
|
||||
$l = new Lexer();
|
||||
$tokens = $l->tokenize('`10`, `1.2`, `-10.20e-10`, `1.2E+2`');
|
||||
$this->assertEquals(10, $tokens[0]['value']);
|
||||
$this->assertEquals(1.2, $tokens[2]['value']);
|
||||
$this->assertEquals(-1.02E-9, $tokens[4]['value']);
|
||||
$this->assertEquals(120, $tokens[6]['value']);
|
||||
}
|
||||
|
||||
public function testCanWorkWithElidedJsonLiterals()
|
||||
{
|
||||
$l = new Lexer();
|
||||
$tokens = $l->tokenize('`foo`');
|
||||
$this->assertEquals('foo', $tokens[0]['value']);
|
||||
$this->assertEquals('literal', $tokens[0]['type']);
|
||||
}
|
||||
}
|
50
vendor/mtdowling/jmespath.php/tests/ParserTest.php
vendored
Normal file
50
vendor/mtdowling/jmespath.php/tests/ParserTest.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\Lexer;
|
||||
use JmesPath\Parser;
|
||||
|
||||
/**
|
||||
* @covers JmesPath\Parser
|
||||
*/
|
||||
class ParserTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \JmesPath\SyntaxErrorException
|
||||
* @expectedExceptionMessage Syntax error at character 0
|
||||
*/
|
||||
public function testMatchesFirstTokens()
|
||||
{
|
||||
$p = new Parser(new Lexer());
|
||||
$p->parse('.bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \JmesPath\SyntaxErrorException
|
||||
* @expectedExceptionMessage Syntax error at character 1
|
||||
*/
|
||||
public function testThrowsSyntaxErrorForInvalidSequence()
|
||||
{
|
||||
$p = new Parser(new Lexer());
|
||||
$p->parse('a,');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \JmesPath\SyntaxErrorException
|
||||
* @expectedExceptionMessage Syntax error at character 2
|
||||
*/
|
||||
public function testMatchesAfterFirstToken()
|
||||
{
|
||||
$p = new Parser(new Lexer());
|
||||
$p->parse('a.,');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \JmesPath\SyntaxErrorException
|
||||
* @expectedExceptionMessage Unexpected "eof" token
|
||||
*/
|
||||
public function testHandlesEmptyExpressions()
|
||||
{
|
||||
(new Parser(new Lexer()))->parse('');
|
||||
}
|
||||
}
|
42
vendor/mtdowling/jmespath.php/tests/SyntaxErrorExceptionTest.php
vendored
Normal file
42
vendor/mtdowling/jmespath.php/tests/SyntaxErrorExceptionTest.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\SyntaxErrorException;
|
||||
|
||||
/**
|
||||
* @covers JmesPath\SyntaxErrorException
|
||||
*/
|
||||
class SyntaxErrorExceptionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreatesWithNoArray()
|
||||
{
|
||||
$e = new SyntaxErrorException(
|
||||
'Found comma',
|
||||
['type' => 'comma', 'pos' => 3, 'value' => ','],
|
||||
'abc,def'
|
||||
);
|
||||
$expected = <<<EOT
|
||||
Syntax error at character 3
|
||||
abc,def
|
||||
^
|
||||
Found comma
|
||||
EOT;
|
||||
$this->assertContains($expected, $e->getMessage());
|
||||
}
|
||||
|
||||
public function testCreatesWithArray()
|
||||
{
|
||||
$e = new SyntaxErrorException(
|
||||
['dot' => true, 'eof' => true],
|
||||
['type' => 'comma', 'pos' => 3, 'value' => ','],
|
||||
'abc,def'
|
||||
);
|
||||
$expected = <<<EOT
|
||||
Syntax error at character 3
|
||||
abc,def
|
||||
^
|
||||
Expected one of the following: dot, eof; found comma ","
|
||||
EOT;
|
||||
$this->assertContains($expected, $e->getMessage());
|
||||
}
|
||||
}
|
23
vendor/mtdowling/jmespath.php/tests/TreeCompilerTest.php
vendored
Normal file
23
vendor/mtdowling/jmespath.php/tests/TreeCompilerTest.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests\Tree;
|
||||
|
||||
use JmesPath\TreeCompiler;
|
||||
|
||||
/**
|
||||
* @covers JmesPath\Tree\TreeCompiler
|
||||
*/
|
||||
class TreeCompilerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreatesSourceCode()
|
||||
{
|
||||
$t = new TreeCompiler();
|
||||
$source = $t->visit(
|
||||
['type' => 'field', 'value' => 'foo'],
|
||||
'testing',
|
||||
'foo'
|
||||
);
|
||||
$this->assertContains('<?php', $source);
|
||||
$this->assertContains('$value = isset($value->{\'foo\'}) ? $value->{\'foo\'} : null;', $source);
|
||||
$this->assertContains('$value = isset($value[\'foo\']) ? $value[\'foo\'] : null;', $source);
|
||||
}
|
||||
}
|
71
vendor/mtdowling/jmespath.php/tests/TreeInterpreterTest.php
vendored
Normal file
71
vendor/mtdowling/jmespath.php/tests/TreeInterpreterTest.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests\Tree;
|
||||
|
||||
use JmesPath\AstRuntime;
|
||||
use JmesPath\TreeInterpreter;
|
||||
|
||||
/**
|
||||
* @covers JmesPath\Tree\TreeInterpreter
|
||||
*/
|
||||
class TreeInterpreterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testReturnsNullWhenMergingNonArray()
|
||||
{
|
||||
$t = new TreeInterpreter();
|
||||
$this->assertNull($t->visit(array(
|
||||
'type' => 'flatten',
|
||||
'children' => array(
|
||||
array('type' => 'literal', 'value' => 1),
|
||||
array('type' => 'literal', 'value' => 1)
|
||||
)
|
||||
), array(), array(
|
||||
'runtime' => new AstRuntime()
|
||||
)));
|
||||
}
|
||||
|
||||
public function testWorksWithArrayObjectAsObject()
|
||||
{
|
||||
$runtime = new AstRuntime();
|
||||
$this->assertEquals('baz', $runtime('foo.bar', new \ArrayObject([
|
||||
'foo' => new \ArrayObject(['bar' => 'baz'])
|
||||
])));
|
||||
}
|
||||
|
||||
public function testWorksWithArrayObjectAsArray()
|
||||
{
|
||||
$runtime = new AstRuntime();
|
||||
$this->assertEquals('baz', $runtime('foo[0].bar', new \ArrayObject([
|
||||
'foo' => new \ArrayObject([new \ArrayObject(['bar' => 'baz'])])
|
||||
])));
|
||||
}
|
||||
|
||||
public function testWorksWithArrayProjections()
|
||||
{
|
||||
$runtime = new AstRuntime();
|
||||
$this->assertEquals(
|
||||
['baz'],
|
||||
$runtime('foo[*].bar', new \ArrayObject([
|
||||
'foo' => new \ArrayObject([
|
||||
new \ArrayObject([
|
||||
'bar' => 'baz'
|
||||
])
|
||||
])
|
||||
]))
|
||||
);
|
||||
}
|
||||
|
||||
public function testWorksWithObjectProjections()
|
||||
{
|
||||
$runtime = new AstRuntime();
|
||||
$this->assertEquals(
|
||||
['baz'],
|
||||
$runtime('foo.*.bar', new \ArrayObject([
|
||||
'foo' => new \ArrayObject([
|
||||
'abc' => new \ArrayObject([
|
||||
'bar' => 'baz'
|
||||
])
|
||||
])
|
||||
]))
|
||||
);
|
||||
}
|
||||
}
|
130
vendor/mtdowling/jmespath.php/tests/UtilsTest.php
vendored
Normal file
130
vendor/mtdowling/jmespath.php/tests/UtilsTest.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace JmesPath\Tests;
|
||||
|
||||
use JmesPath\Utils;
|
||||
|
||||
class UtilsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function typeProvider()
|
||||
{
|
||||
return [
|
||||
['a', 'string'],
|
||||
[10, 'number'],
|
||||
[1.0, 'number'],
|
||||
[true, 'boolean'],
|
||||
[false, 'boolean'],
|
||||
[[], 'array'],
|
||||
[[1, 2], 'array'],
|
||||
[['a' => 1], 'object'],
|
||||
[new \stdClass(), 'object'],
|
||||
[function () {}, 'expression'],
|
||||
[new \ArrayObject(), 'array'],
|
||||
[new \ArrayObject([1, 2]), 'array'],
|
||||
[new \ArrayObject(['foo' => 'bar']), 'object'],
|
||||
[new _TestStr(), 'string']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typeProvider
|
||||
*/
|
||||
public function testGetsTypes($given, $type)
|
||||
{
|
||||
$this->assertEquals($type, Utils::type($given));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testThrowsForInvalidArg()
|
||||
{
|
||||
Utils::type(new _TestClass());
|
||||
}
|
||||
|
||||
public function isArrayProvider()
|
||||
{
|
||||
return [
|
||||
[[], true],
|
||||
[[1, 2], true],
|
||||
[['a' => 1], false],
|
||||
[new _TestClass(), false],
|
||||
[new \ArrayObject(['a' => 'b']), false],
|
||||
[new \ArrayObject([1]), true],
|
||||
[new \stdClass(), false]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider isArrayProvider
|
||||
*/
|
||||
public function testChecksIfArray($given, $result)
|
||||
{
|
||||
$this->assertSame($result, Utils::isArray($given));
|
||||
}
|
||||
|
||||
public function isObjectProvider()
|
||||
{
|
||||
return [
|
||||
[[], true],
|
||||
[[1, 2], false],
|
||||
[['a' => 1], true],
|
||||
[new _TestClass(), false],
|
||||
[new \ArrayObject(['a' => 'b']), true],
|
||||
[new \ArrayObject([1]), false],
|
||||
[new \stdClass(), true]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider isObjectProvider
|
||||
*/
|
||||
public function testChecksIfObject($given, $result)
|
||||
{
|
||||
$this->assertSame($result, Utils::isObject($given));
|
||||
}
|
||||
|
||||
public function testHasStableSort()
|
||||
{
|
||||
$data = [new _TestStr(), new _TestStr(), 0, 10, 2];
|
||||
$result = Utils::stableSort($data, function ($a, $b) {
|
||||
$a = (int) (string) $a;
|
||||
$b = (int) (string) $b;
|
||||
return $a > $b ? -1 : ($a == $b ? 0 : 1);
|
||||
});
|
||||
$this->assertSame($data[0], $result[0]);
|
||||
$this->assertSame($data[1], $result[1]);
|
||||
$this->assertEquals(10, $result[2]);
|
||||
$this->assertEquals(2, $result[3]);
|
||||
$this->assertEquals(0, $result[4]);
|
||||
}
|
||||
|
||||
public function testSlicesArrays()
|
||||
{
|
||||
$this->assertEquals([3, 2, 1], Utils::slice([1, 2, 3], null, null, -1));
|
||||
$this->assertEquals([1, 3], Utils::slice([1, 2, 3], null, null, 2));
|
||||
$this->assertEquals([2, 3], Utils::slice([1, 2, 3], 1));
|
||||
}
|
||||
|
||||
public function testSlicesStrings()
|
||||
{
|
||||
$this->assertEquals('cba', Utils::slice('abc', null, null, -1));
|
||||
$this->assertEquals('ac', Utils::slice('abc', null, null, 2));
|
||||
$this->assertEquals('bc', Utils::slice('abc', 1));
|
||||
}
|
||||
}
|
||||
|
||||
class _TestClass implements \ArrayAccess
|
||||
{
|
||||
public function offsetExists($offset) {}
|
||||
public function offsetGet($offset) {}
|
||||
public function offsetSet($offset, $value) {}
|
||||
public function offsetUnset($offset) {}
|
||||
}
|
||||
|
||||
class _TestStr
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return '100';
|
||||
}
|
||||
}
|
96
vendor/mtdowling/jmespath.php/tests/compliance/basic.json
vendored
Normal file
96
vendor/mtdowling/jmespath.php/tests/compliance/basic.json
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
[{
|
||||
"given":
|
||||
{"foo": {"bar": {"baz": "correct"}}},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": {"bar": {"baz": "correct"}}
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar",
|
||||
"result": {"baz": "correct"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.baz",
|
||||
"result": "correct"
|
||||
},
|
||||
{
|
||||
"expression": "foo\n.\nbar\n.baz",
|
||||
"result": "correct"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.baz.bad",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.bad",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.bad",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "bad",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "bad.morebad.morebad",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given":
|
||||
{"foo": {"bar": ["one", "two", "three"]}},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": {"bar": ["one", "two", "three"]}
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar",
|
||||
"result": ["one", "two", "three"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": ["one", "two", "three"],
|
||||
"cases": [
|
||||
{
|
||||
"expression": "one",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "two",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "three",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "one.two",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given":
|
||||
{"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.\"1\"",
|
||||
"result": ["one", "two", "three"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.\"1\"[0]",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo.\"-1\"",
|
||||
"result": "bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
257
vendor/mtdowling/jmespath.php/tests/compliance/boolean.json
vendored
Normal file
257
vendor/mtdowling/jmespath.php/tests/compliance/boolean.json
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
[
|
||||
{
|
||||
"given": {
|
||||
"outer": {
|
||||
"foo": "foo",
|
||||
"bar": "bar",
|
||||
"baz": "baz"
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "outer.foo || outer.bar",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.foo||outer.bar",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.bar || outer.baz",
|
||||
"result": "bar"
|
||||
},
|
||||
{
|
||||
"expression": "outer.bar||outer.baz",
|
||||
"result": "bar"
|
||||
},
|
||||
{
|
||||
"expression": "outer.bad || outer.foo",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.bad||outer.foo",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.foo || outer.bad",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.foo||outer.bad",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.bad || outer.alsobad",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "outer.bad||outer.alsobad",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"outer": {
|
||||
"foo": "foo",
|
||||
"bool": false,
|
||||
"empty_list": [],
|
||||
"empty_string": ""
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "outer.empty_string || outer.foo",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
|
||||
"result": "foo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"True": true,
|
||||
"False": false,
|
||||
"Number": 5,
|
||||
"EmptyList": [],
|
||||
"Zero": 0
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "True && False",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "False && True",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "True && True",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "False && False",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "True && Number",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "Number && True",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "Number && False",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "Number && EmptyList",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "Number && True",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "EmptyList && True",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "EmptyList && False",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "True || False",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "True || True",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "False || True",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "False || False",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "Number || EmptyList",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "Number || True",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "Number || True && False",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "(Number || True) && False",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "Number || (True && False)",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "!True",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "!False",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "!Number",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "!EmptyList",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "True && !False",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "True && !EmptyList",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "!False && !EmptyList",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "!(True && False)",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "!Zero",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "!!Zero",
|
||||
"result": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"one": 1,
|
||||
"two": 2,
|
||||
"three": 3
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "one < two",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one <= two",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one == one",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one == two",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "one > two",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "one >= two",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "one != two",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one < two && three > one",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one < two || three > one",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "one < two || three < one",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "two < one || three < one",
|
||||
"result": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
25
vendor/mtdowling/jmespath.php/tests/compliance/current.json
vendored
Normal file
25
vendor/mtdowling/jmespath.php/tests/compliance/current.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
[
|
||||
{
|
||||
"given": {
|
||||
"foo": [{"name": "a"}, {"name": "b"}],
|
||||
"bar": {"baz": "qux"}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "@",
|
||||
"result": {
|
||||
"foo": [{"name": "a"}, {"name": "b"}],
|
||||
"bar": {"baz": "qux"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "@.bar",
|
||||
"result": {"baz": "qux"}
|
||||
},
|
||||
{
|
||||
"expression": "@.foo[0]",
|
||||
"result": {"name": "a"}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
46
vendor/mtdowling/jmespath.php/tests/compliance/escape.json
vendored
Normal file
46
vendor/mtdowling/jmespath.php/tests/compliance/escape.json
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
[{
|
||||
"given": {
|
||||
"foo.bar": "dot",
|
||||
"foo bar": "space",
|
||||
"foo\nbar": "newline",
|
||||
"foo\"bar": "doublequote",
|
||||
"c:\\\\windows\\path": "windows",
|
||||
"/unix/path": "unix",
|
||||
"\"\"\"": "threequotes",
|
||||
"bar": {"baz": "qux"}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "\"foo.bar\"",
|
||||
"result": "dot"
|
||||
},
|
||||
{
|
||||
"expression": "\"foo bar\"",
|
||||
"result": "space"
|
||||
},
|
||||
{
|
||||
"expression": "\"foo\\nbar\"",
|
||||
"result": "newline"
|
||||
},
|
||||
{
|
||||
"expression": "\"foo\\\"bar\"",
|
||||
"result": "doublequote"
|
||||
},
|
||||
{
|
||||
"expression": "\"c:\\\\\\\\windows\\\\path\"",
|
||||
"result": "windows"
|
||||
},
|
||||
{
|
||||
"expression": "\"/unix/path\"",
|
||||
"result": "unix"
|
||||
},
|
||||
{
|
||||
"expression": "\"\\\"\\\"\\\"\"",
|
||||
"result": "threequotes"
|
||||
},
|
||||
{
|
||||
"expression": "\"bar\".\"baz\"",
|
||||
"result": "qux"
|
||||
}
|
||||
]
|
||||
}]
|
468
vendor/mtdowling/jmespath.php/tests/compliance/filters.json
vendored
Normal file
468
vendor/mtdowling/jmespath.php/tests/compliance/filters.json
vendored
Normal file
@@ -0,0 +1,468 @@
|
||||
[
|
||||
{
|
||||
"given": {"foo": [{"name": "a"}, {"name": "b"}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Matching a literal",
|
||||
"expression": "foo[?name == 'a']",
|
||||
"result": [{"name": "a"}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [0, 1], "bar": [2, 3]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Matching a literal",
|
||||
"expression": "*[?[0] == `0`]",
|
||||
"result": [[], []]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"first": "foo", "last": "bar"},
|
||||
{"first": "foo", "last": "foo"},
|
||||
{"first": "foo", "last": "baz"}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Matching an expression",
|
||||
"expression": "foo[?first == last]",
|
||||
"result": [{"first": "foo", "last": "foo"}]
|
||||
},
|
||||
{
|
||||
"comment": "Verify projection created from filter",
|
||||
"expression": "foo[?first == last].first",
|
||||
"result": ["foo"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"age": 20},
|
||||
{"age": 25},
|
||||
{"age": 30}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Greater than with a number",
|
||||
"expression": "foo[?age > `25`]",
|
||||
"result": [{"age": 30}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?age >= `25`]",
|
||||
"result": [{"age": 25}, {"age": 30}]
|
||||
},
|
||||
{
|
||||
"comment": "Greater than with a number",
|
||||
"expression": "foo[?age > `30`]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"comment": "Greater than with a number",
|
||||
"expression": "foo[?age < `25`]",
|
||||
"result": [{"age": 20}]
|
||||
},
|
||||
{
|
||||
"comment": "Greater than with a number",
|
||||
"expression": "foo[?age <= `25`]",
|
||||
"result": [{"age": 20}, {"age": 25}]
|
||||
},
|
||||
{
|
||||
"comment": "Greater than with a number",
|
||||
"expression": "foo[?age < `20`]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[?age == `20`]",
|
||||
"result": [{"age": 20}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?age != `20`]",
|
||||
"result": [{"age": 25}, {"age": 30}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"top": {"name": "a"}},
|
||||
{"top": {"name": "b"}}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Filter with subexpression",
|
||||
"expression": "foo[?top.name == 'a']",
|
||||
"result": [{"top": {"name": "a"}}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"top": {"first": "foo", "last": "bar"}},
|
||||
{"top": {"first": "foo", "last": "foo"}},
|
||||
{"top": {"first": "foo", "last": "baz"}}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Matching an expression",
|
||||
"expression": "foo[?top.first == top.last]",
|
||||
"result": [{"top": {"first": "foo", "last": "foo"}}]
|
||||
},
|
||||
{
|
||||
"comment": "Matching a JSON array",
|
||||
"expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]",
|
||||
"result": [{"top": {"first": "foo", "last": "bar"}}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [
|
||||
{"key": true},
|
||||
{"key": false},
|
||||
{"key": 0},
|
||||
{"key": 1},
|
||||
{"key": [0]},
|
||||
{"key": {"bar": [0]}},
|
||||
{"key": null},
|
||||
{"key": [1]},
|
||||
{"key": {"a":2}}
|
||||
]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[?key == `true`]",
|
||||
"result": [{"key": true}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `false`]",
|
||||
"result": [{"key": false}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `0`]",
|
||||
"result": [{"key": 0}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `1`]",
|
||||
"result": [{"key": 1}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `[0]`]",
|
||||
"result": [{"key": [0]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `{\"bar\": [0]}`]",
|
||||
"result": [{"key": {"bar": [0]}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `null`]",
|
||||
"result": [{"key": null}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `[1]`]",
|
||||
"result": [{"key": [1]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key == `{\"a\":2}`]",
|
||||
"result": [{"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`true` == key]",
|
||||
"result": [{"key": true}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`false` == key]",
|
||||
"result": [{"key": false}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`0` == key]",
|
||||
"result": [{"key": 0}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`1` == key]",
|
||||
"result": [{"key": 1}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`[0]` == key]",
|
||||
"result": [{"key": [0]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`{\"bar\": [0]}` == key]",
|
||||
"result": [{"key": {"bar": [0]}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`null` == key]",
|
||||
"result": [{"key": null}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`[1]` == key]",
|
||||
"result": [{"key": [1]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`{\"a\":2}` == key]",
|
||||
"result": [{"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `true`]",
|
||||
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `false`]",
|
||||
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `0`]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `1`]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `null`]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `[1]`]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?key != `{\"a\":2}`]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`true` != key]",
|
||||
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`false` != key]",
|
||||
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`0` != key]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`1` != key]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`null` != key]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`[1]` != key]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?`{\"a\":2}` != key]",
|
||||
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
|
||||
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"reservations": [
|
||||
{"instances": [
|
||||
{"foo": 1, "bar": 2}, {"foo": 1, "bar": 3},
|
||||
{"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "reservations[].instances[?bar==`1`]",
|
||||
"result": [[{"foo": 2, "bar": 1}]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[*].instances[?bar==`1`]",
|
||||
"result": [[{"foo": 2, "bar": 1}]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[?bar==`1`][]",
|
||||
"result": [{"foo": 2, "bar": 1}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"baz": "other",
|
||||
"foo": [
|
||||
{"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[?bar==`1`].bar[0]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
{"a": 1, "b": {"c": "x"}},
|
||||
{"a": 1, "b": {"c": "y"}},
|
||||
{"a": 1, "b": {"c": "z"}},
|
||||
{"a": 2, "b": {"c": "z"}},
|
||||
{"a": 1, "baz": 2}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[?a==`1`].b.c",
|
||||
"result": ["x", "y", "z"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Filter with or expression",
|
||||
"expression": "foo[?name == 'a' || name == 'b']",
|
||||
"result": [{"name": "a"}, {"name": "b"}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?name == 'a' || name == 'e']",
|
||||
"result": [{"name": "a"}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?name == 'a' || name == 'b' || name == 'c']",
|
||||
"result": [{"name": "a"}, {"name": "b"}, {"name": "c"}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Filter with and expression",
|
||||
"expression": "foo[?a == `1` && b == `2`]",
|
||||
"result": [{"a": 1, "b": 2}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?a == `1` && b == `4`]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Filter with Or and And expressions",
|
||||
"expression": "foo[?c == `3` || a == `1` && b == `4`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?b == `2` || a == `3` && b == `4`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?a == `3` && b == `4` || b == `2`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?(a == `3` && b == `4`) || b == `2`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?((a == `3` && b == `4`)) || b == `2`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?a == `3` && (b == `4` || b == `2`)]",
|
||||
"result": [{"a": 3, "b": 4}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[?a == `3` && ((b == `4` || b == `2`))]",
|
||||
"result": [{"a": 3, "b": 4}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Verify precedence of or/and expressions",
|
||||
"expression": "foo[?a == `1` || b ==`2` && c == `5`]",
|
||||
"result": [{"a": 1, "b": 2, "c": 3}]
|
||||
},
|
||||
{
|
||||
"comment": "Parentheses can alter precedence",
|
||||
"expression": "foo[?(a == `1` || b ==`2`) && c == `5`]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"comment": "Not expressions combined with and/or",
|
||||
"expression": "foo[?!(a == `1` || b ==`2`)]",
|
||||
"result": [{"a": 3, "b": 4}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
{"key": true},
|
||||
{"key": false},
|
||||
{"key": []},
|
||||
{"key": {}},
|
||||
{"key": [0]},
|
||||
{"key": {"a": "b"}},
|
||||
{"key": 0},
|
||||
{"key": 1},
|
||||
{"key": null},
|
||||
{"notkey": true}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Unary filter expression",
|
||||
"expression": "foo[?key]",
|
||||
"result": [
|
||||
{"key": true}, {"key": [0]}, {"key": {"a": "b"}},
|
||||
{"key": 0}, {"key": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Unary not filter expression",
|
||||
"expression": "foo[?!key]",
|
||||
"result": [
|
||||
{"key": false}, {"key": []}, {"key": {}},
|
||||
{"key": null}, {"notkey": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Equality with null RHS",
|
||||
"expression": "foo[?key == `null`]",
|
||||
"result": [
|
||||
{"key": null}, {"notkey": true}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Using @ in a filter expression",
|
||||
"expression": "foo[?@ < `5`]",
|
||||
"result": [0, 1, 2, 3, 4]
|
||||
},
|
||||
{
|
||||
"comment": "Using @ in a filter expression",
|
||||
"expression": "foo[?`5` > @]",
|
||||
"result": [0, 1, 2, 3, 4]
|
||||
},
|
||||
{
|
||||
"comment": "Using @ in a filter expression",
|
||||
"expression": "foo[?@ == @]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
821
vendor/mtdowling/jmespath.php/tests/compliance/functions.json
vendored
Normal file
821
vendor/mtdowling/jmespath.php/tests/compliance/functions.json
vendored
Normal file
@@ -0,0 +1,821 @@
|
||||
[{
|
||||
"given":
|
||||
{
|
||||
"foo": -1,
|
||||
"zero": 0,
|
||||
"numbers": [-1, 3, 4, 5],
|
||||
"array": [-1, 3, 4, 5, "a", "100"],
|
||||
"strings": ["a", "b", "c"],
|
||||
"decimals": [1.01, 1.2, -1.5],
|
||||
"str": "Str",
|
||||
"false": false,
|
||||
"empty_list": [],
|
||||
"empty_hash": {},
|
||||
"objects": {"foo": "bar", "bar": "baz"},
|
||||
"null_key": null
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "abs(foo)",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "abs(foo)",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "abs(str)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "abs(array[1])",
|
||||
"result": 3
|
||||
},
|
||||
{
|
||||
"expression": "abs(array[1])",
|
||||
"result": 3
|
||||
},
|
||||
{
|
||||
"expression": "abs(`false`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "abs(`-24`)",
|
||||
"result": 24
|
||||
},
|
||||
{
|
||||
"expression": "abs(`-24`)",
|
||||
"result": 24
|
||||
},
|
||||
{
|
||||
"expression": "abs(`1`, `2`)",
|
||||
"error": "invalid-arity"
|
||||
},
|
||||
{
|
||||
"expression": "abs()",
|
||||
"error": "invalid-arity"
|
||||
},
|
||||
{
|
||||
"expression": "unknown_function(`1`, `2`)",
|
||||
"error": "unknown-function"
|
||||
},
|
||||
{
|
||||
"expression": "avg(numbers)",
|
||||
"result": 2.75
|
||||
},
|
||||
{
|
||||
"expression": "avg(array)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "avg('abc')",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "avg(foo)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "avg(@)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "avg(strings)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "ceil(`1.2`)",
|
||||
"result": 2
|
||||
},
|
||||
{
|
||||
"expression": "ceil(decimals[0])",
|
||||
"result": 2
|
||||
},
|
||||
{
|
||||
"expression": "ceil(decimals[1])",
|
||||
"result": 2
|
||||
},
|
||||
{
|
||||
"expression": "ceil(decimals[2])",
|
||||
"result": -1
|
||||
},
|
||||
{
|
||||
"expression": "ceil('string')",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "contains('abc', 'a')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "contains('abc', 'd')",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "contains(`false`, 'd')",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "contains(strings, 'a')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "contains(decimals, `1.2`)",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "contains(decimals, `false`)",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, 'r')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, 'tr')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, 'Str')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, 'SStr')",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, 'foo')",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "ends_with(str, `0`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "floor(`1.2`)",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "floor('string')",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "floor(decimals[0])",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "floor(foo)",
|
||||
"result": -1
|
||||
},
|
||||
{
|
||||
"expression": "floor(str)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "length('abc')",
|
||||
"result": 3
|
||||
},
|
||||
{
|
||||
"expression": "length('')",
|
||||
"result": 0
|
||||
},
|
||||
{
|
||||
"expression": "length(@)",
|
||||
"result": 12
|
||||
},
|
||||
{
|
||||
"expression": "length(strings[0])",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "length(str)",
|
||||
"result": 3
|
||||
},
|
||||
{
|
||||
"expression": "length(array)",
|
||||
"result": 6
|
||||
},
|
||||
{
|
||||
"expression": "length(objects)",
|
||||
"result": 2
|
||||
},
|
||||
{
|
||||
"expression": "length(`false`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "length(foo)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "length(strings[0])",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "max(numbers)",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "max(decimals)",
|
||||
"result": 1.2
|
||||
},
|
||||
{
|
||||
"expression": "max(strings)",
|
||||
"result": "c"
|
||||
},
|
||||
{
|
||||
"expression": "max(abc)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "max(array)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "max(decimals)",
|
||||
"result": 1.2
|
||||
},
|
||||
{
|
||||
"expression": "max(empty_list)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "merge(`{}`)",
|
||||
"result": {}
|
||||
},
|
||||
{
|
||||
"expression": "merge(`{}`, `{}`)",
|
||||
"result": {}
|
||||
},
|
||||
{
|
||||
"expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)",
|
||||
"result": {"a": 1, "b": 2}
|
||||
},
|
||||
{
|
||||
"expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)",
|
||||
"result": {"a": 2}
|
||||
},
|
||||
{
|
||||
"expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)",
|
||||
"result": {"a": 2, "b": 2, "c": 3, "d": 4}
|
||||
},
|
||||
{
|
||||
"expression": "min(numbers)",
|
||||
"result": -1
|
||||
},
|
||||
{
|
||||
"expression": "min(decimals)",
|
||||
"result": -1.5
|
||||
},
|
||||
{
|
||||
"expression": "min(abc)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "min(array)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "min(empty_list)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "min(decimals)",
|
||||
"result": -1.5
|
||||
},
|
||||
{
|
||||
"expression": "min(strings)",
|
||||
"result": "a"
|
||||
},
|
||||
{
|
||||
"expression": "type('abc')",
|
||||
"result": "string"
|
||||
},
|
||||
{
|
||||
"expression": "type(`1.0`)",
|
||||
"result": "number"
|
||||
},
|
||||
{
|
||||
"expression": "type(`2`)",
|
||||
"result": "number"
|
||||
},
|
||||
{
|
||||
"expression": "type(`true`)",
|
||||
"result": "boolean"
|
||||
},
|
||||
{
|
||||
"expression": "type(`false`)",
|
||||
"result": "boolean"
|
||||
},
|
||||
{
|
||||
"expression": "type(`null`)",
|
||||
"result": "null"
|
||||
},
|
||||
{
|
||||
"expression": "type(`[0]`)",
|
||||
"result": "array"
|
||||
},
|
||||
{
|
||||
"expression": "type(`{\"a\": \"b\"}`)",
|
||||
"result": "object"
|
||||
},
|
||||
{
|
||||
"expression": "type(@)",
|
||||
"result": "object"
|
||||
},
|
||||
{
|
||||
"expression": "sort(keys(objects))",
|
||||
"result": ["bar", "foo"]
|
||||
},
|
||||
{
|
||||
"expression": "keys(foo)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "keys(strings)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "keys(`false`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort(values(objects))",
|
||||
"result": ["bar", "baz"]
|
||||
},
|
||||
{
|
||||
"expression": "keys(empty_hash)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "values(foo)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "join(', ', strings)",
|
||||
"result": "a, b, c"
|
||||
},
|
||||
{
|
||||
"expression": "join(', ', strings)",
|
||||
"result": "a, b, c"
|
||||
},
|
||||
{
|
||||
"expression": "join(',', `[\"a\", \"b\"]`)",
|
||||
"result": "a,b"
|
||||
},
|
||||
{
|
||||
"expression": "join(',', `[\"a\", 0]`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "join(', ', str)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "join('|', strings)",
|
||||
"result": "a|b|c"
|
||||
},
|
||||
{
|
||||
"expression": "join(`2`, strings)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "join('|', decimals)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "join('|', decimals[].to_string(@))",
|
||||
"result": "1.01|1.2|-1.5"
|
||||
},
|
||||
{
|
||||
"expression": "join('|', empty_list)",
|
||||
"result": ""
|
||||
},
|
||||
{
|
||||
"expression": "reverse(numbers)",
|
||||
"result": [5, 4, 3, -1]
|
||||
},
|
||||
{
|
||||
"expression": "reverse(array)",
|
||||
"result": ["100", "a", 5, 4, 3, -1]
|
||||
},
|
||||
{
|
||||
"expression": "reverse(`[]`)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "reverse('')",
|
||||
"result": ""
|
||||
},
|
||||
{
|
||||
"expression": "reverse('hello world')",
|
||||
"result": "dlrow olleh"
|
||||
},
|
||||
{
|
||||
"expression": "starts_with(str, 'S')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "starts_with(str, 'St')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "starts_with(str, 'Str')",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "starts_with(str, 'String')",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "starts_with(str, `0`)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sum(numbers)",
|
||||
"result": 11
|
||||
},
|
||||
{
|
||||
"expression": "sum(decimals)",
|
||||
"result": 0.71
|
||||
},
|
||||
{
|
||||
"expression": "sum(array)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sum(array[].to_number(@))",
|
||||
"result": 111
|
||||
},
|
||||
{
|
||||
"expression": "sum(`[]`)",
|
||||
"result": 0
|
||||
},
|
||||
{
|
||||
"expression": "to_array('foo')",
|
||||
"result": ["foo"]
|
||||
},
|
||||
{
|
||||
"expression": "to_array(`0`)",
|
||||
"result": [0]
|
||||
},
|
||||
{
|
||||
"expression": "to_array(objects)",
|
||||
"result": [{"foo": "bar", "bar": "baz"}]
|
||||
},
|
||||
{
|
||||
"expression": "to_array(`[1, 2, 3]`)",
|
||||
"result": [1, 2, 3]
|
||||
},
|
||||
{
|
||||
"expression": "to_array(false)",
|
||||
"result": [false]
|
||||
},
|
||||
{
|
||||
"expression": "to_string('foo')",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "to_string(`1.2`)",
|
||||
"result": "1.2"
|
||||
},
|
||||
{
|
||||
"expression": "to_string(`[0, 1]`)",
|
||||
"result": "[0,1]"
|
||||
},
|
||||
{
|
||||
"expression": "to_number('1.0')",
|
||||
"result": 1.0
|
||||
},
|
||||
{
|
||||
"expression": "to_number('1.1')",
|
||||
"result": 1.1
|
||||
},
|
||||
{
|
||||
"expression": "to_number('4')",
|
||||
"result": 4
|
||||
},
|
||||
{
|
||||
"expression": "to_number('notanumber')",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "to_number(`false`)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "to_number(`null`)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "to_number(`[0]`)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "to_number(`{\"foo\": 0}`)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "\"to_string\"(`1.0`)",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "sort(numbers)",
|
||||
"result": [-1, 3, 4, 5]
|
||||
},
|
||||
{
|
||||
"expression": "sort(strings)",
|
||||
"result": ["a", "b", "c"]
|
||||
},
|
||||
{
|
||||
"expression": "sort(decimals)",
|
||||
"result": [-1.5, 1.01, 1.2]
|
||||
},
|
||||
{
|
||||
"expression": "sort(array)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort(abc)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort(empty_list)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "sort(@)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "not_null(unknown_key, str)",
|
||||
"result": "Str"
|
||||
},
|
||||
{
|
||||
"expression": "not_null(unknown_key, foo.bar, empty_list, str)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "not_null(unknown_key, null_key, empty_list, str)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "not_null(all, expressions, are_null)",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "not_null()",
|
||||
"error": "invalid-arity"
|
||||
},
|
||||
{
|
||||
"description": "function projection on single arg function",
|
||||
"expression": "numbers[].to_string(@)",
|
||||
"result": ["-1", "3", "4", "5"]
|
||||
},
|
||||
{
|
||||
"description": "function projection on single arg function",
|
||||
"expression": "array[].to_number(@)",
|
||||
"result": [-1, 3, 4, 5, 100]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given":
|
||||
{
|
||||
"foo": [
|
||||
{"b": "b", "a": "a"},
|
||||
{"c": "c", "b": "b"},
|
||||
{"d": "d", "c": "c"},
|
||||
{"e": "e", "d": "d"},
|
||||
{"f": "f", "e": "e"}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"description": "function projection on variadic function",
|
||||
"expression": "foo[].not_null(f, e, d, c, b, a)",
|
||||
"result": ["b", "c", "d", "e", "f"]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given":
|
||||
{
|
||||
"people": [
|
||||
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
|
||||
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
|
||||
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
|
||||
{"age": 50, "age_str": "50", "bool": false, "name": "d"},
|
||||
{"age": 10, "age_str": "10", "bool": true, "name": 3}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"description": "sort by field expression",
|
||||
"expression": "sort_by(people, &age)",
|
||||
"result": [
|
||||
{"age": 10, "age_str": "10", "bool": true, "name": 3},
|
||||
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
|
||||
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
|
||||
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
|
||||
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, &age_str)",
|
||||
"result": [
|
||||
{"age": 10, "age_str": "10", "bool": true, "name": 3},
|
||||
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
|
||||
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
|
||||
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
|
||||
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "sort by function expression",
|
||||
"expression": "sort_by(people, &to_number(age_str))",
|
||||
"result": [
|
||||
{"age": 10, "age_str": "10", "bool": true, "name": 3},
|
||||
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
|
||||
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
|
||||
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
|
||||
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "function projection on sort_by function",
|
||||
"expression": "sort_by(people, &age)[].name",
|
||||
"result": [3, "a", "c", "b", "d"]
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, &extra)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, &bool)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, &name)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, name)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(people, &age)[].extra",
|
||||
"result": ["foo", "bar"]
|
||||
},
|
||||
{
|
||||
"expression": "sort_by(`[]`, &age)",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "max_by(people, &age)",
|
||||
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
},
|
||||
{
|
||||
"expression": "max_by(people, &age_str)",
|
||||
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
},
|
||||
{
|
||||
"expression": "max_by(people, &bool)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "max_by(people, &extra)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "max_by(people, &to_number(age_str))",
|
||||
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
|
||||
},
|
||||
{
|
||||
"expression": "min_by(people, &age)",
|
||||
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
|
||||
},
|
||||
{
|
||||
"expression": "min_by(people, &age_str)",
|
||||
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
|
||||
},
|
||||
{
|
||||
"expression": "min_by(people, &bool)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "min_by(people, &extra)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "min_by(people, &to_number(age_str))",
|
||||
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given":
|
||||
{
|
||||
"people": [
|
||||
{"age": 10, "order": "1"},
|
||||
{"age": 10, "order": "2"},
|
||||
{"age": 10, "order": "3"},
|
||||
{"age": 10, "order": "4"},
|
||||
{"age": 10, "order": "5"},
|
||||
{"age": 10, "order": "6"},
|
||||
{"age": 10, "order": "7"},
|
||||
{"age": 10, "order": "8"},
|
||||
{"age": 10, "order": "9"},
|
||||
{"age": 10, "order": "10"},
|
||||
{"age": 10, "order": "11"}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"description": "stable sort order",
|
||||
"expression": "sort_by(people, &age)",
|
||||
"result": [
|
||||
{"age": 10, "order": "1"},
|
||||
{"age": 10, "order": "2"},
|
||||
{"age": 10, "order": "3"},
|
||||
{"age": 10, "order": "4"},
|
||||
{"age": 10, "order": "5"},
|
||||
{"age": 10, "order": "6"},
|
||||
{"age": 10, "order": "7"},
|
||||
{"age": 10, "order": "8"},
|
||||
{"age": 10, "order": "9"},
|
||||
{"age": 10, "order": "10"},
|
||||
{"age": 10, "order": "11"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given":
|
||||
{
|
||||
"people": [
|
||||
{"a": 10, "b": 1, "c": "z"},
|
||||
{"a": 10, "b": 2, "c": null},
|
||||
{"a": 10, "b": 3},
|
||||
{"a": 10, "b": 4, "c": "z"},
|
||||
{"a": 10, "b": 5, "c": null},
|
||||
{"a": 10, "b": 6},
|
||||
{"a": 10, "b": 7, "c": "z"},
|
||||
{"a": 10, "b": 8, "c": null},
|
||||
{"a": 10, "b": 9}
|
||||
],
|
||||
"empty": []
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "map(&a, people)",
|
||||
"result": [10, 10, 10, 10, 10, 10, 10, 10, 10]
|
||||
},
|
||||
{
|
||||
"expression": "map(&c, people)",
|
||||
"result": ["z", null, null, "z", null, null, "z", null, null]
|
||||
},
|
||||
{
|
||||
"expression": "map(&a, badkey)",
|
||||
"error": "invalid-type"
|
||||
},
|
||||
{
|
||||
"expression": "map(&foo, empty)",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"array": [
|
||||
{
|
||||
"foo": {"bar": "yes1"}
|
||||
},
|
||||
{
|
||||
"foo": {"bar": "yes2"}
|
||||
},
|
||||
{
|
||||
"foo1": {"bar": "no"}
|
||||
}
|
||||
]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "map(&foo.bar, array)",
|
||||
"result": ["yes1", "yes2", null]
|
||||
},
|
||||
{
|
||||
"expression": "map(&foo1.bar, array)",
|
||||
"result": [null, null, "no"]
|
||||
},
|
||||
{
|
||||
"expression": "map(&foo.bar.baz, array)",
|
||||
"result": [null, null, null]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "map(&[], array)",
|
||||
"result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
1377
vendor/mtdowling/jmespath.php/tests/compliance/identifiers.json
vendored
Normal file
1377
vendor/mtdowling/jmespath.php/tests/compliance/identifiers.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
346
vendor/mtdowling/jmespath.php/tests/compliance/indices.json
vendored
Normal file
346
vendor/mtdowling/jmespath.php/tests/compliance/indices.json
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
[{
|
||||
"given":
|
||||
{"foo": {"bar": ["zero", "one", "two"]}},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.bar[0]",
|
||||
"result": "zero"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[1]",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[2]",
|
||||
"result": "two"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[3]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[-1]",
|
||||
"result": "two"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[-2]",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[-3]",
|
||||
"result": "zero"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[-4]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given":
|
||||
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.bar",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[0].bar",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo[1].bar",
|
||||
"result": "two"
|
||||
},
|
||||
{
|
||||
"expression": "foo[2].bar",
|
||||
"result": "three"
|
||||
},
|
||||
{
|
||||
"expression": "foo[3].notbar",
|
||||
"result": "four"
|
||||
},
|
||||
{
|
||||
"expression": "foo[3].bar",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[0]",
|
||||
"result": {"bar": "one"}
|
||||
},
|
||||
{
|
||||
"expression": "foo[1]",
|
||||
"result": {"bar": "two"}
|
||||
},
|
||||
{
|
||||
"expression": "foo[2]",
|
||||
"result": {"bar": "three"}
|
||||
},
|
||||
{
|
||||
"expression": "foo[3]",
|
||||
"result": {"notbar": "four"}
|
||||
},
|
||||
{
|
||||
"expression": "foo[4]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": [
|
||||
"one", "two", "three"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"expression": "[0]",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "[1]",
|
||||
"result": "two"
|
||||
},
|
||||
{
|
||||
"expression": "[2]",
|
||||
"result": "three"
|
||||
},
|
||||
{
|
||||
"expression": "[-1]",
|
||||
"result": "three"
|
||||
},
|
||||
{
|
||||
"expression": "[-2]",
|
||||
"result": "two"
|
||||
},
|
||||
{
|
||||
"expression": "[-3]",
|
||||
"result": "one"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"reservations": [
|
||||
{"instances": [{"foo": 1}, {"foo": 2}]}
|
||||
]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "reservations[].instances[].foo",
|
||||
"result": [1, 2]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].bar",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].notinstances[].foo",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].notinstances[].foo",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"reservations": [{
|
||||
"instances": [
|
||||
{"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
|
||||
{"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
|
||||
{"foo": "bar"},
|
||||
{"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]},
|
||||
{"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]},
|
||||
{"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]},
|
||||
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
|
||||
],
|
||||
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
|
||||
}, {
|
||||
"instances": [
|
||||
{"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
|
||||
{"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
|
||||
{"c": "bar"},
|
||||
{"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]},
|
||||
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
|
||||
],
|
||||
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
|
||||
}
|
||||
]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "reservations[].instances[].foo[].bar",
|
||||
"result": [1, 2, 4, 5, 6, 8]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].foo[].baz",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].notfoo[].bar",
|
||||
"result": [20, 21, 22, 23, 24, 25]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].notfoo[].notbar",
|
||||
"result": [[7], [7]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].notinstances[].foo",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].foo[].notbar",
|
||||
"result": [3, [7]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].bar[].baz",
|
||||
"result": [[1], [2], [3], [4]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].baz[].baz",
|
||||
"result": [[1, 2], [], [], [3, 4]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].qux[].baz",
|
||||
"result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].qux[].baz[]",
|
||||
"result": [1, 2, 3, 4, 1, 2, 3, 4]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
[["one", "two"], ["three", "four"]],
|
||||
[["five", "six"], ["seven", "eight"]],
|
||||
[["nine"], ["ten"]]
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[]",
|
||||
"result": [["one", "two"], ["three", "four"], ["five", "six"],
|
||||
["seven", "eight"], ["nine"], ["ten"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[][0]",
|
||||
"result": ["one", "three", "five", "seven", "nine", "ten"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[][1]",
|
||||
"result": ["two", "four", "six", "eight"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[][0][0]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[][2][2]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[][0][0][100]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [{
|
||||
"bar": [
|
||||
{
|
||||
"qux": 2,
|
||||
"baz": 1
|
||||
},
|
||||
{
|
||||
"qux": 4,
|
||||
"baz": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"bar": [
|
||||
{
|
||||
"qux": 6,
|
||||
"baz": 5
|
||||
},
|
||||
{
|
||||
"qux": 8,
|
||||
"baz": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
|
||||
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[]",
|
||||
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
|
||||
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar",
|
||||
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
|
||||
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[]",
|
||||
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
|
||||
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[].baz",
|
||||
"result": [1, 3, 5, 7]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"string": "string",
|
||||
"hash": {"foo": "bar", "bar": "baz"},
|
||||
"number": 23,
|
||||
"nullvalue": null
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "string[]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "hash[]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "number[]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "string[].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "hash[].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "number[].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[].foo[].bar",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
190
vendor/mtdowling/jmespath.php/tests/compliance/literal.json
vendored
Normal file
190
vendor/mtdowling/jmespath.php/tests/compliance/literal.json
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
[
|
||||
{
|
||||
"given": {
|
||||
"foo": [{"name": "a"}, {"name": "b"}],
|
||||
"bar": {"baz": "qux"}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "`\"foo\"`",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"comment": "Interpret escaped unicode.",
|
||||
"expression": "`\"\\u03a6\"`",
|
||||
"result": "Φ"
|
||||
},
|
||||
{
|
||||
"expression": "`\"✓\"`",
|
||||
"result": "✓"
|
||||
},
|
||||
{
|
||||
"expression": "`[1, 2, 3]`",
|
||||
"result": [1, 2, 3]
|
||||
},
|
||||
{
|
||||
"expression": "`{\"a\": \"b\"}`",
|
||||
"result": {"a": "b"}
|
||||
},
|
||||
{
|
||||
"expression": "`true`",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"expression": "`false`",
|
||||
"result": false
|
||||
},
|
||||
{
|
||||
"expression": "`null`",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "`0`",
|
||||
"result": 0
|
||||
},
|
||||
{
|
||||
"expression": "`1`",
|
||||
"result": 1
|
||||
},
|
||||
{
|
||||
"expression": "`2`",
|
||||
"result": 2
|
||||
},
|
||||
{
|
||||
"expression": "`3`",
|
||||
"result": 3
|
||||
},
|
||||
{
|
||||
"expression": "`4`",
|
||||
"result": 4
|
||||
},
|
||||
{
|
||||
"expression": "`5`",
|
||||
"result": 5
|
||||
},
|
||||
{
|
||||
"expression": "`6`",
|
||||
"result": 6
|
||||
},
|
||||
{
|
||||
"expression": "`7`",
|
||||
"result": 7
|
||||
},
|
||||
{
|
||||
"expression": "`8`",
|
||||
"result": 8
|
||||
},
|
||||
{
|
||||
"expression": "`9`",
|
||||
"result": 9
|
||||
},
|
||||
{
|
||||
"comment": "Escaping a backtick in quotes",
|
||||
"expression": "`\"foo\\`bar\"`",
|
||||
"result": "foo`bar"
|
||||
},
|
||||
{
|
||||
"comment": "Double quote in literal",
|
||||
"expression": "`\"foo\\\"bar\"`",
|
||||
"result": "foo\"bar"
|
||||
},
|
||||
{
|
||||
"expression": "`\"1\\`\"`",
|
||||
"result": "1`"
|
||||
},
|
||||
{
|
||||
"comment": "Multiple literal expressions with escapes",
|
||||
"expression": "`\"\\\\\"`.{a:`\"b\"`}",
|
||||
"result": {"a": "b"}
|
||||
},
|
||||
{
|
||||
"comment": "literal . identifier",
|
||||
"expression": "`{\"a\": \"b\"}`.a",
|
||||
"result": "b"
|
||||
},
|
||||
{
|
||||
"comment": "literal . identifier . identifier",
|
||||
"expression": "`{\"a\": {\"b\": \"c\"}}`.a.b",
|
||||
"result": "c"
|
||||
},
|
||||
{
|
||||
"comment": "literal . identifier bracket-expr",
|
||||
"expression": "`[0, 1, 2]`[1]",
|
||||
"result": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Literals",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Literal with leading whitespace",
|
||||
"expression": "` {\"foo\": true}`",
|
||||
"result": {"foo": true}
|
||||
},
|
||||
{
|
||||
"comment": "Literal with trailing whitespace",
|
||||
"expression": "`{\"foo\": true} `",
|
||||
"result": {"foo": true}
|
||||
},
|
||||
{
|
||||
"comment": "Literal on RHS of subexpr not allowed",
|
||||
"expression": "foo.`\"bar\"`",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Raw String Literals",
|
||||
"given": {},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "'foo'",
|
||||
"result": "foo"
|
||||
},
|
||||
{
|
||||
"expression": "' foo '",
|
||||
"result": " foo "
|
||||
},
|
||||
{
|
||||
"expression": "'0'",
|
||||
"result": "0"
|
||||
},
|
||||
{
|
||||
"expression": "'newline\n'",
|
||||
"result": "newline\n"
|
||||
},
|
||||
{
|
||||
"expression": "'\n'",
|
||||
"result": "\n"
|
||||
},
|
||||
{
|
||||
"expression": "'✓'",
|
||||
"result": "✓"
|
||||
},
|
||||
{
|
||||
"expression": "'𝄞'",
|
||||
"result": "𝄞"
|
||||
},
|
||||
{
|
||||
"expression": "' [foo] '",
|
||||
"result": " [foo] "
|
||||
},
|
||||
{
|
||||
"expression": "'[foo]'",
|
||||
"result": "[foo]"
|
||||
},
|
||||
{
|
||||
"comment": "Do not interpret escaped unicode.",
|
||||
"expression": "'\\u03a6'",
|
||||
"result": "\\u03a6"
|
||||
},
|
||||
{
|
||||
"comment": "Can escape the single quote",
|
||||
"expression": "'foo\\'bar'",
|
||||
"result": "foo'bar"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
393
vendor/mtdowling/jmespath.php/tests/compliance/multiselect.json
vendored
Normal file
393
vendor/mtdowling/jmespath.php/tests/compliance/multiselect.json
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
[{
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": "bar",
|
||||
"baz": "baz",
|
||||
"qux": "qux",
|
||||
"nested": {
|
||||
"one": {
|
||||
"a": "first",
|
||||
"b": "second",
|
||||
"c": "third"
|
||||
},
|
||||
"two": {
|
||||
"a": "first",
|
||||
"b": "second",
|
||||
"c": "third"
|
||||
},
|
||||
"three": {
|
||||
"a": "first",
|
||||
"b": "second",
|
||||
"c": {"inner": "third"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"bar": 1,
|
||||
"baz": 2,
|
||||
"qux\"": 3
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.{bar: bar}",
|
||||
"result": {"bar": "bar"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{\"bar\": bar}",
|
||||
"result": {"bar": "bar"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{\"foo.bar\": bar}",
|
||||
"result": {"foo.bar": "bar"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{bar: bar, baz: baz}",
|
||||
"result": {"bar": "bar", "baz": "baz"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{\"bar\": bar, \"baz\": baz}",
|
||||
"result": {"bar": "bar", "baz": "baz"}
|
||||
},
|
||||
{
|
||||
"expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}",
|
||||
"result": {"baz": 2, "qux\"": 3}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{bar:bar,baz:baz}",
|
||||
"result": {"bar": "bar", "baz": "baz"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{bar: bar,qux: qux}",
|
||||
"result": {"bar": "bar", "qux": "qux"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{bar: bar, noexist: noexist}",
|
||||
"result": {"bar": "bar", "noexist": null}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}",
|
||||
"result": {"noexist": null, "alsonoexist": null}
|
||||
},
|
||||
{
|
||||
"expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.nested.*.{a: a,b: b}",
|
||||
"result": [{"a": "first", "b": "second"},
|
||||
{"a": "first", "b": "second"},
|
||||
{"a": "first", "b": "second"}]
|
||||
},
|
||||
{
|
||||
"expression": "foo.nested.three.{a: a, cinner: c.inner}",
|
||||
"result": {"a": "first", "cinner": "third"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.nested.three.{a: a, c: c.inner.bad.key}",
|
||||
"result": {"a": "first", "c": null}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{a: nested.one.a, b: nested.two.b}",
|
||||
"result": {"a": "first", "b": "second"}
|
||||
},
|
||||
{
|
||||
"expression": "{bar: bar, baz: baz}",
|
||||
"result": {"bar": 1, "baz": 2}
|
||||
},
|
||||
{
|
||||
"expression": "{bar: bar}",
|
||||
"result": {"bar": 1}
|
||||
},
|
||||
{
|
||||
"expression": "{otherkey: bar}",
|
||||
"result": {"otherkey": 1}
|
||||
},
|
||||
{
|
||||
"expression": "{no: no, exist: exist}",
|
||||
"result": {"no": null, "exist": null}
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar]",
|
||||
"result": ["bar"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz]",
|
||||
"result": ["bar", "baz"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,qux]",
|
||||
"result": ["bar", "qux"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,noexist]",
|
||||
"result": ["bar", null]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[noexist,alsonoexist]",
|
||||
"result": [null, null]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {"bar": 1, "baz": [2, 3, 4]}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.{bar:bar,baz:baz}",
|
||||
"result": {"bar": 1, "baz": [2, 3, 4]}
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz[0]]",
|
||||
"result": [1, 2]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz[1]]",
|
||||
"result": [1, 3]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz[2]]",
|
||||
"result": [1, 4]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz[3]]",
|
||||
"result": [1, null]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar[0],baz[3]]",
|
||||
"result": [null, null]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {"bar": 1, "baz": 2}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.{bar: bar, baz: baz}",
|
||||
"result": {"bar": 1, "baz": 2}
|
||||
},
|
||||
{
|
||||
"expression": "foo.[bar,baz]",
|
||||
"result": [1, 2]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": {"baz": [{"common": "first", "one": 1},
|
||||
{"common": "second", "two": 2}]},
|
||||
"ignoreme": 1,
|
||||
"includeme": true
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.{bar: bar.baz[1],includeme: includeme}",
|
||||
"result": {"bar": {"common": "second", "two": 2}, "includeme": true}
|
||||
},
|
||||
{
|
||||
"expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}",
|
||||
"result": {"bar.baz.two": 2, "includeme": true}
|
||||
},
|
||||
{
|
||||
"expression": "foo.[includeme, bar.baz[*].common]",
|
||||
"result": [true, ["first", "second"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[includeme, bar.baz[*].none]",
|
||||
"result": [true, []]
|
||||
},
|
||||
{
|
||||
"expression": "foo.[includeme, bar.baz[].common]",
|
||||
"result": [true, ["first", "second"]]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"reservations": [{
|
||||
"instances": [
|
||||
{"id": "id1",
|
||||
"name": "first"},
|
||||
{"id": "id2",
|
||||
"name": "second"}
|
||||
]}, {
|
||||
"instances": [
|
||||
{"id": "id3",
|
||||
"name": "third"},
|
||||
{"id": "id4",
|
||||
"name": "fourth"}
|
||||
]}
|
||||
]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "reservations[*].instances[*].{id: id, name: name}",
|
||||
"result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}],
|
||||
[{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].{id: id, name: name}",
|
||||
"result": [{"id": "id1", "name": "first"},
|
||||
{"id": "id2", "name": "second"},
|
||||
{"id": "id3", "name": "third"},
|
||||
{"id": "id4", "name": "fourth"}]
|
||||
},
|
||||
{
|
||||
"expression": "reservations[].instances[].[id, name]",
|
||||
"result": [["id1", "first"],
|
||||
["id2", "second"],
|
||||
["id3", "third"],
|
||||
["id4", "fourth"]]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [{
|
||||
"bar": [
|
||||
{
|
||||
"qux": 2,
|
||||
"baz": 1
|
||||
},
|
||||
{
|
||||
"qux": 4,
|
||||
"baz": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"bar": [
|
||||
{
|
||||
"qux": 6,
|
||||
"baz": 5
|
||||
},
|
||||
{
|
||||
"qux": 8,
|
||||
"baz": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
|
||||
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[]",
|
||||
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
|
||||
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar",
|
||||
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
|
||||
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[]",
|
||||
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
|
||||
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[].[baz, qux]",
|
||||
"result": [[1, 2], [3, 4], [5, 6], [7, 8]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[].[baz]",
|
||||
"result": [[1], [3], [5], [7]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[].bar[].[baz, qux][]",
|
||||
"result": [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": {
|
||||
"baz": [
|
||||
{
|
||||
"bar": "abc"
|
||||
}, {
|
||||
"bar": "def"
|
||||
}
|
||||
],
|
||||
"qux": ["zero"]
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.[baz[*].bar, qux[0]]",
|
||||
"result": [["abc", "def"], "zero"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": {
|
||||
"baz": [
|
||||
{
|
||||
"bar": "a",
|
||||
"bam": "b",
|
||||
"boo": "c"
|
||||
}, {
|
||||
"bar": "d",
|
||||
"bam": "e",
|
||||
"boo": "f"
|
||||
}
|
||||
],
|
||||
"qux": ["zero"]
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.[baz[*].[bar, boo], qux[0]]",
|
||||
"result": [[["a", "c" ], ["d", "f" ]], "zero"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": {
|
||||
"baz": [
|
||||
{
|
||||
"bar": "a",
|
||||
"bam": "b",
|
||||
"boo": "c"
|
||||
}, {
|
||||
"bar": "d",
|
||||
"bam": "e",
|
||||
"boo": "f"
|
||||
}
|
||||
],
|
||||
"qux": ["zero"]
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]",
|
||||
"result": [["a", "d"], "zero"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Nested multiselect",
|
||||
"expression": "[[*],*]",
|
||||
"result": [null, ["object"]]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": [],
|
||||
"cases": [
|
||||
{
|
||||
"comment": "Nested multiselect",
|
||||
"expression": "[[*]]",
|
||||
"result": [[]]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
27
vendor/mtdowling/jmespath.php/tests/compliance/perf/basic.json
vendored
Normal file
27
vendor/mtdowling/jmespath.php/tests/compliance/perf/basic.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
[{
|
||||
"description": "Basic minimal case",
|
||||
"given":
|
||||
{"foo": {"bar": {"baz": "correct"}}},
|
||||
"cases": [
|
||||
{
|
||||
"name": "single_expression",
|
||||
"expression": "foo",
|
||||
"result": {"bar": {"baz": "correct"}}
|
||||
},
|
||||
{
|
||||
"name": "single_dot_expression",
|
||||
"expression": "foo.bar",
|
||||
"result": {"baz": "correct"}
|
||||
},
|
||||
{
|
||||
"name": "double_dot_expression",
|
||||
"expression": "foo.bar.baz",
|
||||
"result": "correct"
|
||||
},
|
||||
{
|
||||
"name": "dot_no_match",
|
||||
"expression": "foo.bar.baz.bad",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
}]
|
27
vendor/mtdowling/jmespath.php/tests/compliance/perf/deep_hierarchy.json
vendored
Normal file
27
vendor/mtdowling/jmespath.php/tests/compliance/perf/deep_hierarchy.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
[{
|
||||
"description": "Deeply nested dict",
|
||||
"given":
|
||||
{"j49": {"j48": {"j47": {"j46": {"j45": {"j44": {"j43": {"j42": {"j41": {"j40": {"j39": {"j38": {"j37": {"j36": {"j35": {"j34": {"j33": {"j32": {"j31": {"j30": {"j29": {"j28": {"j27": {"j26": {"j25": {"j24": {"j23": {"j22": {"j21": {"j20": {"j19": {"j18": {"j17": {"j16": {"j15": {"j14": {"j13": {"j12": {"j11": {"j10": {"j9": {"j8": {"j7": {"j6": {"j5": {"j4": {"j3": {"j2": {"j1": {"j0": {}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
|
||||
"cases": [
|
||||
{
|
||||
"name": "deep_nesting_10",
|
||||
"expression": "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40",
|
||||
"result": {"j39": {"j38": {"j37": {"j36": {"j35": {"j34": {"j33": {"j32": {"j31": {"j30": {"j29": {"j28": {"j27": {"j26": {"j25": {"j24": {"j23": {"j22": {"j21": {"j20": {"j19": {"j18": {"j17": {"j16": {"j15": {"j14": {"j13": {"j12": {"j11": {"j10": {"j9": {"j8": {"j7": {"j6": {"j5": {"j4": {"j3": {"j2": {"j1": {"j0": {}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
|
||||
},
|
||||
{
|
||||
"name": "deep_nesting_50",
|
||||
"expression": "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40.j39.j38.j37.j36.j35.j34.j33.j32.j31.j30.j29.j28.j27.j26.j25.j24.j23.j22.j21.j20.j19.j18.j17.j16.j15.j14.j13.j12.j11.j10.j9.j8.j7.j6.j5.j4.j3.j2.j1.j0",
|
||||
"result": {}
|
||||
},
|
||||
{
|
||||
"name": "deep_nesting_50_pipe",
|
||||
"expression": "j49|j48|j47|j46|j45|j44|j43|j42|j41|j40|j39|j38|j37|j36|j35|j34|j33|j32|j31|j30|j29|j28|j27|j26|j25|j24|j23|j22|j21|j20|j19|j18|j17|j16|j15|j14|j13|j12|j11|j10|j9|j8|j7|j6|j5|j4|j3|j2|j1|j0",
|
||||
"result": {}
|
||||
},
|
||||
{
|
||||
"name": "deep_nesting_50_index",
|
||||
"expression": "[49][48][47][46][45][44][43][42][41][40][39][38][37][36][35][34][33][32][31][30][29][28][27][26][25][24][23][22][21][20][19][18][17][16][15][14][13][12][11][10][9][8][7][6][5][4][3][2][1][0]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
}]
|
12
vendor/mtdowling/jmespath.php/tests/compliance/perf/deep_projection.json
vendored
Normal file
12
vendor/mtdowling/jmespath.php/tests/compliance/perf/deep_projection.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
[{
|
||||
"description": "Deep projections",
|
||||
"given":
|
||||
{"a": []},
|
||||
"cases": [
|
||||
{
|
||||
"name": "deep_projection_104",
|
||||
"expression": "a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
}]
|
17
vendor/mtdowling/jmespath.php/tests/compliance/perf/functions.json
vendored
Normal file
17
vendor/mtdowling/jmespath.php/tests/compliance/perf/functions.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
[{
|
||||
"description": "Deep projections",
|
||||
"given":
|
||||
[749, 222, 102, 148, 869, 848, 326, 644, 402, 150, 361, 827, 741, 60, 842, 943, 214, 519, 134, 866, 621, 851, 59, 580, 760, 576, 951, 989, 266, 259, 809, 643, 292, 731, 129, 970, 589, 430, 690, 715, 901, 491, 276, 88, 738, 282, 547, 349, 236, 879, 403, 557, 554, 23, 649, 720, 531, 2, 601, 152, 530, 477, 568, 122, 811, 75, 181, 203, 683, 152, 794, 155, 54, 314, 957, 468, 740, 532, 504, 806, 927, 827, 840, 100, 519, 357, 536, 398, 417, 543, 599, 383, 144, 772, 988, 184, 118, 921, 497, 193, 320, 919, 583, 346, 575, 143, 866, 907, 570, 255, 539, 164, 764, 256, 315, 305, 960, 587, 804, 577, 667, 869, 563, 956, 677, 469, 934, 52, 323, 933, 398, 305, 138, 133, 443, 419, 717, 838, 287, 177, 192, 210, 892, 319, 470, 76, 643, 737, 135, 425, 586, 882, 844, 113, 268, 323, 938, 569, 374, 295, 648, 27, 703, 530, 667, 118, 176, 972, 611, 60, 47, 19, 500, 344, 332, 452, 647, 388, 188, 235, 151, 353, 219, 766, 626, 885, 456, 182, 363, 617, 236, 285, 152, 87, 666, 429, 599, 762, 13, 778, 634, 43, 199, 361, 300, 370, 957, 488, 359, 354, 972, 368, 482, 88, 766, 709, 804, 637, 368, 950, 752, 932, 638, 291, 177, 739, 740, 357, 928, 964, 621, 472, 813, 36, 271, 642, 3, 771, 397, 670, 324, 244, 827, 194, 693, 846, 351, 668, 911, 600, 682, 735, 26, 876, 581, 915, 184, 263, 857, 960, 5, 523, 932, 694, 457, 739, 897, 28, 794, 885, 77, 768, 39, 763, 748, 792, 60, 582, 667, 909, 820, 898, 569, 252, 583, 237, 677, 613, 914, 956, 541, 297, 853, 581, 118, 888, 368, 156, 582, 183],
|
||||
"cases": [
|
||||
{
|
||||
"name": "min sort with slice",
|
||||
"expression": "sort(@)[:3]",
|
||||
"result": [2, 3, 5]
|
||||
},
|
||||
{
|
||||
"name": "max sort with slice",
|
||||
"expression": "sort(@)[-3:]",
|
||||
"result": [972, 988, 989]
|
||||
}
|
||||
]
|
||||
}]
|
22
vendor/mtdowling/jmespath.php/tests/compliance/perf/multiwildcard.json
vendored
Normal file
22
vendor/mtdowling/jmespath.php/tests/compliance/perf/multiwildcard.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
[{
|
||||
"description": "Multiple wildcards in an expression",
|
||||
"given": {
|
||||
"foo": [
|
||||
{"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
|
||||
{"bar": [{"kind": "advanced"}, {"kind": "expert"}]}
|
||||
]
|
||||
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"name": "multi_wildcard_field",
|
||||
"expression": "foo[*].bar[*].kind",
|
||||
"result": [["basic", "intermediate"], ["advanced", "expert"]]
|
||||
},
|
||||
{
|
||||
"name": "wildcard_with_index",
|
||||
"expression": "foo[*].bar[0].kind",
|
||||
"result": ["basic", "advanced"]
|
||||
}
|
||||
]
|
||||
}]
|
17
vendor/mtdowling/jmespath.php/tests/compliance/perf/wildcardindex.json
vendored
Normal file
17
vendor/mtdowling/jmespath.php/tests/compliance/perf/wildcardindex.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
[{
|
||||
"description": "Multiple wildcards",
|
||||
"given":
|
||||
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
|
||||
"cases": [
|
||||
{
|
||||
"name": "wildcard_with_field_match",
|
||||
"expression": "foo[*].bar",
|
||||
"result": ["one", "two", "three"]
|
||||
},
|
||||
{
|
||||
"name": "wildcard_with_field_match2",
|
||||
"expression": "foo[*].notbar",
|
||||
"result": ["four"]
|
||||
}
|
||||
]
|
||||
}]
|
131
vendor/mtdowling/jmespath.php/tests/compliance/pipe.json
vendored
Normal file
131
vendor/mtdowling/jmespath.php/tests/compliance/pipe.json
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
[{
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": {
|
||||
"baz": "subkey"
|
||||
},
|
||||
"other": {
|
||||
"baz": "subkey"
|
||||
},
|
||||
"other2": {
|
||||
"baz": "subkey"
|
||||
},
|
||||
"other3": {
|
||||
"notbaz": ["a", "b", "c"]
|
||||
},
|
||||
"other4": {
|
||||
"notbaz": ["a", "b", "c"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.*.baz | [0]",
|
||||
"result": "subkey"
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.baz | [1]",
|
||||
"result": "subkey"
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.baz | [2]",
|
||||
"result": "subkey"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.* | [0]",
|
||||
"result": "subkey"
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.notbaz | [*]",
|
||||
"result": [["a", "b", "c"], ["a", "b", "c"]]
|
||||
},
|
||||
{
|
||||
"expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz",
|
||||
"result": ["subkey", "subkey"]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": {
|
||||
"baz": "one"
|
||||
},
|
||||
"other": {
|
||||
"baz": "two"
|
||||
},
|
||||
"other2": {
|
||||
"baz": "three"
|
||||
},
|
||||
"other3": {
|
||||
"notbaz": ["a", "b", "c"]
|
||||
},
|
||||
"other4": {
|
||||
"notbaz": ["d", "e", "f"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo | bar",
|
||||
"result": {"baz": "one"}
|
||||
},
|
||||
{
|
||||
"expression": "foo | bar | baz",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo|bar| baz",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "not_there | [0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "not_there | [0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "[foo.bar, foo.other] | [0]",
|
||||
"result": {"baz": "one"}
|
||||
},
|
||||
{
|
||||
"expression": "{\"a\": foo.bar, \"b\": foo.other} | a",
|
||||
"result": {"baz": "one"}
|
||||
},
|
||||
{
|
||||
"expression": "{\"a\": foo.bar, \"b\": foo.other} | b",
|
||||
"result": {"baz": "two"}
|
||||
},
|
||||
{
|
||||
"expression": "foo.bam || foo.bar | baz",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo | not_there || bar",
|
||||
"result": {"baz": "one"}
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": [{
|
||||
"bar": [{
|
||||
"baz": "one"
|
||||
}, {
|
||||
"baz": "two"
|
||||
}]
|
||||
}, {
|
||||
"bar": [{
|
||||
"baz": "three"
|
||||
}, {
|
||||
"baz": "four"
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar[*] | [0][0]",
|
||||
"result": {"baz": "one"}
|
||||
}
|
||||
]
|
||||
}]
|
187
vendor/mtdowling/jmespath.php/tests/compliance/slice.json
vendored
Normal file
187
vendor/mtdowling/jmespath.php/tests/compliance/slice.json
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
[{
|
||||
"given": {
|
||||
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
"bar": {
|
||||
"baz": 1
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "bar[0:10]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:10:1]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:10]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:10:]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0::1]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0::]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[:10:1]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[::1]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[:10:]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[::]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[:]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[1:9]",
|
||||
"result": [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:10:2]",
|
||||
"result": [0, 2, 4, 6, 8]
|
||||
},
|
||||
{
|
||||
"expression": "foo[5:]",
|
||||
"result": [5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[5::2]",
|
||||
"result": [5, 7, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[::2]",
|
||||
"result": [0, 2, 4, 6, 8]
|
||||
},
|
||||
{
|
||||
"expression": "foo[::-1]",
|
||||
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
||||
},
|
||||
{
|
||||
"expression": "foo[1::2]",
|
||||
"result": [1, 3, 5, 7, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[10:0:-1]",
|
||||
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1]
|
||||
},
|
||||
{
|
||||
"expression": "foo[10:5:-1]",
|
||||
"result": [9, 8, 7, 6]
|
||||
},
|
||||
{
|
||||
"expression": "foo[8:2:-2]",
|
||||
"result": [8, 6, 4]
|
||||
},
|
||||
{
|
||||
"expression": "foo[0:20]",
|
||||
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
},
|
||||
{
|
||||
"expression": "foo[10:-20:-1]",
|
||||
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
||||
},
|
||||
{
|
||||
"expression": "foo[10:-20]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[-4:-1]",
|
||||
"result": [6, 7, 8]
|
||||
},
|
||||
{
|
||||
"expression": "foo[:-5:-1]",
|
||||
"result": [9, 8, 7, 6]
|
||||
},
|
||||
{
|
||||
"expression": "foo[8:2:0]",
|
||||
"error": "invalid-value"
|
||||
},
|
||||
{
|
||||
"expression": "foo[8:2:0:1]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[8:2&]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[2:a:3]",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": [{"a": 1}, {"a": 2}, {"a": 3}],
|
||||
"bar": [{"a": {"b": 1}}, {"a": {"b": 2}},
|
||||
{"a": {"b": 3}}],
|
||||
"baz": 50
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[:2].a",
|
||||
"result": [1, 2]
|
||||
},
|
||||
{
|
||||
"expression": "foo[:2].b",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[:2].a.b",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "bar[::-1].a.b",
|
||||
"result": [3, 2, 1]
|
||||
},
|
||||
{
|
||||
"expression": "bar[:2].a.b",
|
||||
"result": [1, 2]
|
||||
},
|
||||
{
|
||||
"expression": "baz[:2].a",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": [{"a": 1}, {"a": 2}, {"a": 3}],
|
||||
"cases": [
|
||||
{
|
||||
"expression": "[:]",
|
||||
"result": [{"a": 1}, {"a": 2}, {"a": 3}]
|
||||
},
|
||||
{
|
||||
"expression": "[:2].a",
|
||||
"result": [1, 2]
|
||||
},
|
||||
{
|
||||
"expression": "[::-1].a",
|
||||
"result": [3, 2, 1]
|
||||
},
|
||||
{
|
||||
"expression": "[:2].b",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
}]
|
616
vendor/mtdowling/jmespath.php/tests/compliance/syntax.json
vendored
Normal file
616
vendor/mtdowling/jmespath.php/tests/compliance/syntax.json
vendored
Normal file
@@ -0,0 +1,616 @@
|
||||
[{
|
||||
"comment": "Dot syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.bar",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.1",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.-11",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": ".foo",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo..bar",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[.]",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Simple token errors",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": ".",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": ":",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": ",",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "[",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "{",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": ")",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "(",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "((&",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "a[",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "a]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "a][",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "!",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Boolean syntax errors",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "![!(!",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Wildcard syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "*",
|
||||
"result": ["object"]
|
||||
},
|
||||
{
|
||||
"expression": "*.*",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "*.foo",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "*[0]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": ".*",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "*foo",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "*0",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[*]bar",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[*]*",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Flatten syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "[]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Simple bracket syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "[0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "*.[0]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "*.[\"0\"]",
|
||||
"result": [[null]]
|
||||
},
|
||||
{
|
||||
"expression": "[*].bar",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "[*][0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[#]",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select list syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Valid multi-select of a list",
|
||||
"expression": "foo[0, 1]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.[0]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list with trailing comma",
|
||||
"expression": "foo[0, ]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list with trailing comma and no close",
|
||||
"expression": "foo[0,",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list with trailing comma and no close",
|
||||
"expression": "foo.[a",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list with extra comma",
|
||||
"expression": "foo[0,, 1]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list using an identifier index",
|
||||
"expression": "foo[abc]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list using identifier indices",
|
||||
"expression": "foo[abc, def]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list using an identifier index",
|
||||
"expression": "foo[abc, 1]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a list using an identifier index with trailing comma",
|
||||
"expression": "foo[abc, ]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Valid multi-select of a hash using an identifier index",
|
||||
"expression": "foo.[abc]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Valid multi-select of a hash",
|
||||
"expression": "foo.[abc, def]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a hash using a numeric index",
|
||||
"expression": "foo.[abc, 1]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a hash with a trailing comma",
|
||||
"expression": "foo.[abc, ]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a hash with extra commas",
|
||||
"expression": "foo.[abc,, def]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select of a hash using number indices",
|
||||
"expression": "foo.[0, 1]",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Multi-select hash syntax",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"comment": "No key or value",
|
||||
"expression": "a{}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "No closing token",
|
||||
"expression": "a{",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Not a key value pair",
|
||||
"expression": "a{foo}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value and closing character",
|
||||
"expression": "a{foo:",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing closing character",
|
||||
"expression": "a{foo: 0",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value",
|
||||
"expression": "a{foo:}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Trailing comma and no closing character",
|
||||
"expression": "a{foo: 0, ",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value with trailing comma",
|
||||
"expression": "a{foo: ,}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Accessing Array using an identifier",
|
||||
"expression": "a{foo: bar}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "a{foo: 0}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing key-value pair",
|
||||
"expression": "a.{}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Not a key-value pair",
|
||||
"expression": "a.{foo}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value",
|
||||
"expression": "a.{foo:}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value with trailing comma",
|
||||
"expression": "a.{foo: ,}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Valid multi-select hash extraction",
|
||||
"expression": "a.{foo: bar}",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Valid multi-select hash extraction",
|
||||
"expression": "a.{foo: bar, baz: bam}",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Trailing comma",
|
||||
"expression": "a.{foo: bar, }",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing key in second key-value pair",
|
||||
"expression": "a.{foo: bar, baz}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Missing value in second key-value pair",
|
||||
"expression": "a.{foo: bar, baz:}",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Trailing comma",
|
||||
"expression": "a.{foo: bar, baz: bam, }",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Nested multi select",
|
||||
"expression": "{\"\\\\\":{\" \":*}}",
|
||||
"result": {"\\": {" ": ["object"]}}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Or expressions",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo || bar",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo ||",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.|| bar",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": " || foo",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo || || foo",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo.[a || b]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.[a ||]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "\"foo",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Filter expressions",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[?bar==`\"baz\"`]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[? bar == `\"baz\"` ]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[ ?bar==`\"baz\"`]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[?bar==]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[?==]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[?==bar]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[?bar==baz?]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[?a.b.c==d.e.f]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[?bar==`[0, 1, 2]`]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[?bar==`[\"a\", \"b\", \"c\"]`]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Literal char not escaped",
|
||||
"expression": "foo[?bar==`[\"foo`bar\"]`]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Literal char escaped",
|
||||
"expression": "foo[?bar==`[\"foo\\`bar\"]`]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Unknown comparator",
|
||||
"expression": "foo[?bar<>baz]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Unknown comparator",
|
||||
"expression": "foo[?bar^baz]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[bar==baz]",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Quoted identifier in filter expression no spaces",
|
||||
"expression": "[?\"\\\\\">`\"foo\"`]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"comment": "Quoted identifier in filter expression with spaces",
|
||||
"expression": "[?\"\\\\\" > `\"foo\"`]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Filter expression errors",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "bar.`\"anything\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "bar.baz.noexists.`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Literal wildcard projection",
|
||||
"expression": "foo[*].`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[*].name.`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[].name.`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[].name.`\"literal\"`.`\"subliteral\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Projecting a literal onto an empty list",
|
||||
"expression": "foo[*].name.noexist.`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "foo[].name.noexist.`\"literal\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"expression": "twolen[*].`\"foo\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Two level projection of a literal",
|
||||
"expression": "twolen[*].threelen[*].`\"bar\"`",
|
||||
"error": "syntax"
|
||||
},
|
||||
{
|
||||
"comment": "Two level flattened projection of a literal",
|
||||
"expression": "twolen[].threelen[].`\"bar\"`",
|
||||
"error": "syntax"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Identifiers",
|
||||
"given": {"type": "object"},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "\"foo\"",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "\"\\\\\"",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Combined syntax",
|
||||
"given": [],
|
||||
"cases": [
|
||||
{
|
||||
"expression": "*||*|*|*",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "*[]||[*]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "[*.*]",
|
||||
"result": [[]]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
38
vendor/mtdowling/jmespath.php/tests/compliance/unicode.json
vendored
Normal file
38
vendor/mtdowling/jmespath.php/tests/compliance/unicode.json
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"given": {"foo": [{"✓": "✓"}, {"✓": "✗"}]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[].\"✓\"",
|
||||
"result": ["✓", "✗"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"☯": true},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "\"☯\"",
|
||||
"result": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪": true},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "\"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪\"",
|
||||
"result": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {"☃": true},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "\"☃\"",
|
||||
"result": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
460
vendor/mtdowling/jmespath.php/tests/compliance/wildcard.json
vendored
Normal file
460
vendor/mtdowling/jmespath.php/tests/compliance/wildcard.json
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
[{
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": {
|
||||
"baz": "val"
|
||||
},
|
||||
"other": {
|
||||
"baz": "val"
|
||||
},
|
||||
"other2": {
|
||||
"baz": "val"
|
||||
},
|
||||
"other3": {
|
||||
"notbaz": ["a", "b", "c"]
|
||||
},
|
||||
"other4": {
|
||||
"notbaz": ["a", "b", "c"]
|
||||
},
|
||||
"other5": {
|
||||
"other": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.*.baz",
|
||||
"result": ["val", "val", "val"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar.*",
|
||||
"result": ["val"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.notbaz",
|
||||
"result": [["a", "b", "c"], ["a", "b", "c"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.notbaz[0]",
|
||||
"result": ["a", "a"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.notbaz[-1]",
|
||||
"result": ["c", "c"]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {
|
||||
"first-1": {
|
||||
"second-1": "val"
|
||||
},
|
||||
"first-2": {
|
||||
"second-1": "val"
|
||||
},
|
||||
"first-3": {
|
||||
"second-1": "val"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.*",
|
||||
"result": [{"second-1": "val"}, {"second-1": "val"},
|
||||
{"second-1": "val"}]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.*",
|
||||
"result": [["val"], ["val"], ["val"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.*.*",
|
||||
"result": [[], [], []]
|
||||
},
|
||||
{
|
||||
"expression": "foo.*.*.*.*",
|
||||
"result": [[], [], []]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": "one"
|
||||
},
|
||||
"other": {
|
||||
"bar": "one"
|
||||
},
|
||||
"nomatch": {
|
||||
"notbar": "three"
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "*.bar",
|
||||
"result": ["one", "one"]
|
||||
}
|
||||
]
|
||||
}, {
|
||||
"given": {
|
||||
"top1": {
|
||||
"sub1": {"foo": "one"}
|
||||
},
|
||||
"top2": {
|
||||
"sub1": {"foo": "one"}
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "*",
|
||||
"result": [{"sub1": {"foo": "one"}},
|
||||
{"sub1": {"foo": "one"}}]
|
||||
},
|
||||
{
|
||||
"expression": "*.sub1",
|
||||
"result": [{"foo": "one"},
|
||||
{"foo": "one"}]
|
||||
},
|
||||
{
|
||||
"expression": "*.*",
|
||||
"result": [[{"foo": "one"}],
|
||||
[{"foo": "one"}]]
|
||||
},
|
||||
{
|
||||
"expression": "*.*.foo[]",
|
||||
"result": ["one", "one"]
|
||||
},
|
||||
{
|
||||
"expression": "*.sub1.foo",
|
||||
"result": ["one", "one"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given":
|
||||
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar",
|
||||
"result": ["one", "two", "three"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*].notbar",
|
||||
"result": ["four"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given":
|
||||
[{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}],
|
||||
"cases": [
|
||||
{
|
||||
"expression": "[*]",
|
||||
"result": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]
|
||||
},
|
||||
{
|
||||
"expression": "[*].bar",
|
||||
"result": ["one", "two", "three"]
|
||||
},
|
||||
{
|
||||
"expression": "[*].notbar",
|
||||
"result": ["four"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": [
|
||||
{"baz": ["one", "two", "three"]},
|
||||
{"baz": ["four", "five", "six"]},
|
||||
{"baz": ["seven", "eight", "nine"]}
|
||||
]
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.bar[*].baz",
|
||||
"result": [["one", "two", "three"], ["four", "five", "six"], ["seven", "eight", "nine"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[*].baz[0]",
|
||||
"result": ["one", "four", "seven"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[*].baz[1]",
|
||||
"result": ["two", "five", "eight"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[*].baz[2]",
|
||||
"result": ["three", "six", "nine"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[*].baz[3]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": {
|
||||
"bar": [["one", "two"], ["three", "four"]]
|
||||
}
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo.bar[*]",
|
||||
"result": [["one", "two"], ["three", "four"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[0]",
|
||||
"result": ["one", "two"]
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[0][0]",
|
||||
"result": "one"
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[0][0][0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo.bar[0][0][0][0]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "foo[0][0]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
{"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
|
||||
{"bar": [{"kind": "advanced"}, {"kind": "expert"}]},
|
||||
{"bar": "string"}
|
||||
]
|
||||
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar[*].kind",
|
||||
"result": [["basic", "intermediate"], ["advanced", "expert"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*].bar[0].kind",
|
||||
"result": ["basic", "advanced"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
{"bar": {"kind": "basic"}},
|
||||
{"bar": {"kind": "intermediate"}},
|
||||
{"bar": {"kind": "advanced"}},
|
||||
{"bar": {"kind": "expert"}},
|
||||
{"bar": "string"}
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar.kind",
|
||||
"result": ["basic", "intermediate", "advanced", "expert"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [{"bar": ["one", "two"]}, {"bar": ["three", "four"]}, {"bar": ["five"]}]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar[0]",
|
||||
"result": ["one", "three", "five"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*].bar[1]",
|
||||
"result": ["two", "four"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*].bar[2]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [{"bar": []}, {"bar": []}, {"bar": []}]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*].bar[0]",
|
||||
"result": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [["one", "two"], ["three", "four"], ["five"]]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*][0]",
|
||||
"result": ["one", "three", "five"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][1]",
|
||||
"result": ["two", "four"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"foo": [
|
||||
[
|
||||
["one", "two"], ["three", "four"]
|
||||
], [
|
||||
["five", "six"], ["seven", "eight"]
|
||||
], [
|
||||
["nine"], ["ten"]
|
||||
]
|
||||
]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "foo[*][0]",
|
||||
"result": [["one", "two"], ["five", "six"], ["nine"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][1]",
|
||||
"result": [["three", "four"], ["seven", "eight"], ["ten"]]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][0][0]",
|
||||
"result": ["one", "five", "nine"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][1][0]",
|
||||
"result": ["three", "seven", "ten"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][0][1]",
|
||||
"result": ["two", "six"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][1][1]",
|
||||
"result": ["four", "eight"]
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][2]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "foo[*][2][2]",
|
||||
"result": []
|
||||
},
|
||||
{
|
||||
"expression": "bar[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "bar[*].baz[*]",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"string": "string",
|
||||
"hash": {"foo": "bar", "bar": "baz"},
|
||||
"number": 23,
|
||||
"nullvalue": null
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "string[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "hash[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "number[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[*]",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "string[*].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "hash[*].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "number[*].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[*].foo",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue[*].foo[*].bar",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"string": "string",
|
||||
"hash": {"foo": "val", "bar": "val"},
|
||||
"number": 23,
|
||||
"array": [1, 2, 3],
|
||||
"nullvalue": null
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "string.*",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "hash.*",
|
||||
"result": ["val", "val"]
|
||||
},
|
||||
{
|
||||
"expression": "number.*",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "array.*",
|
||||
"result": null
|
||||
},
|
||||
{
|
||||
"expression": "nullvalue.*",
|
||||
"result": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"a": [0, 1, 2],
|
||||
"b": [0, 1, 2]
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"expression": "*[0]",
|
||||
"result": [0, 0]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
Reference in New Issue
Block a user